I have a BFS algorithm error.
Have tried to debug with the gdb but I don't understand why I get this.
Can anyone tell me why i get a SIGSEGV error with the code below. Does it depend on the compiler that you use how the pointers are addressed? As there is an invalid pointer error in the code
#include<iostream>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
using namespace std;
const int MAX = 8;
struct Node
{
int data;
Node *next;
};
class Graph
{
private:
int visited[MAX];
int q[8];
int front, rear;
public:
Graph();
void BFS(int v, Node **p);
Node *getNode_Write(int val);
static void addQueue(int *a, int vertex, int *f, int *r);
static int deleteQueue(int *q, int *f, int *r);
static int isEmpty(int *f);
void del(Node *n);
};
// initialize data memeber
Graph::Graph()
{
for(int i = 0; i < MAX; i++)
visited[i] = FALSE;
front = rear = -1;
}
// function that implements breadth first search (BFS) algorithm
void Graph::BFS(int v, Node **p)
{
Node *u;
visited[v-1] = TRUE;
cout<<v<<"\t";
addQueue(q, v, &front, &rear);
while(isEmpty(&front) == FALSE)
{
v = deleteQueue(q, &front, &rear);
u = *(p+v-1);
while(u != NULL)
{
if(visited[u->data-1] == FALSE)
{
addQueue(q, u->data, &front, & rear);
visited[u->data-1] == TRUE;
cout<<u->data<<"\t";
}
u = u->next;
}
}
}
// Creates a node
Node *Graph::getNode_Write(int val)
{
Node *newNode = new Node;
newNode->data = val;
return newNode;
}
//Adds node to the queue
void Graph::addQueue(int *a, int vertex, int *f, int *r)
{
if(*r == MAX -1)
{
cout<<"\nQueue Overflow.";
exit(0);
}
(*r)++;
a[*r] = vertex;
if(*f == -1)
*r = 0;
}
// Deletes a node from the queue
int Graph::deleteQueue(int *a, int *f, int *r)
{
int data;
if(*f == -1)
{
cout<<"\nQueue Underflow";
exit(0);
}
data = a[*f];
if(*f == *r)
*f = *r = -1;
else
(*f)++;
return data;
}
// checks if queque is empty
int Graph::isEmpty(int *f)
{
if(*f == -1)
return TRUE;
return FALSE;
}
// deallocate the memory
void Graph::del(Node *n)
{
Node *temp;
while(n != NULL)
{
temp = n->next;
delete n;
n = temp;
}
}
int main()
{
Node *arr[MAX];
Node *v1,*v2,*v3,*v4;
Graph g;
v1 = g.getNode_Write(2);
arr[0] = v1;
v1->next = v2 = g.getNode_Write(3);
v2->next = NULL;
v1 = g.getNode_Write(1);
arr[1] = v1;
v1->next = v2 = g.getNode_Write(4);
v2->next = v3 = g.getNode_Write(5);
v3->next = NULL;
cout<<endl;
g.BFS(1,arr);
for(int i = 0; i<MAX; i++)
g.del(arr[i]);
}
There is an uninitialized array arr in the stack frame of main. Only arr[0] and arr[1] become initialized. At the end of main it is iterated over the whole array and delete is called in Graph::del(Node *n) on a garbage value.
"Does it depend on the compiler that you use how the pointers are addressed?"
No, it doesn't depend on the compiler primarily. As Joachim pointed out in his comment:
To see the real source of the error, you should just step up the stack trace, and check out how all the variables and parameters were actually set.
Most likely you've been calling some undefined behavior, due to missing, or wrong variable initializations.
Related
This is a program of searching a number from linked list using recursion.
#include <iostream>
using namespace std;
class node {
public:
int data;
node *next;
void create(int *,int);
int max(node*,int);
};
node *first;
void node::create(int a[],int n) {
first = new node;
first->data = a[0];
first->next = NULL;
node *last = first;
for (int i = 1; i < n; i++) {
node *t = new node;
t->data = a[i];
t->next = NULL;
last->next = t;
last = t;
}
}
int node::max(node *l, int p) {
if (l->data == p) {
return 1;
}
if (l == 0)
return 0;
else {
max(l->next, p);
return 0;
}
}
int main() {
int a[5] = {1,2,3,4,5};
node m;
m.create(a,5);
cout << m.max(first, 3);
return 0;
}
Hunch. Instead of this:
else {
max(l->next, p);
return 0;
}
This:
else {
return max(l->next, p);
}
Or better yet, let's fix the whole max function to check for null before dereferencing l as well.
int node::max(node *l, int p) {
int result = 0;
if (l != nullptr) {
if (l->data == p) {
result = 1;
}
else {
result = max(l->next, p);
}
}
return result;
}
I am trying to implement a skiplist in cpp . There are many versions of skiplist available but I particularly want to implement a version where each node has a right and down pointer to form a connected list at various levels . Also at each higher level there is a replica of node rather than just a pointer.
I am giving my code that I have implemented uptill now. There is only one function that I have implemented till now i.e insertion. But I am getting segmentation fault. I know I am messing somewhere with pointers somewhere either in constructor, update or insert functions. Can somebody please help.
class SkipList
{
private:
struct node {
int key;
int data;
int level;
struct node* rgt = nullptr;
struct node* dwn = nullptr ;
node(int k, int value, int l):
key(k), data(value), level(l)
{}
};
//generates the ndde level in tha range [1,maxLevel).
int randomLevel() const;
//returns a set of pointers to the location at each node where new links are to be created
std::vector<node*> update(int searchKey) const ;
//creates a new node and returns a pointer to it
static node* makeNode(int key, int val, int level);
const float probability;
const int maxLevel;
// head and tail vectors
vector<node*> head;
vector<node*> nil;
public:
SkipList();
~SkipList();
void insert(int searchKey, int val);
void print() const;
};
SkipList::SkipList() :
probability(0.5), maxLevel(16)
{
int headkey = std::numeric_limits<int>::min();
int nilkey = std::numeric_limits<int>::max();
for(int i = 0; i < maxLevel;i++)
{
head[i] = new node(headkey,0,maxLevel-1);
nil[i] = new node(nilkey,0,maxLevel-1);
if(i > 0)
{
head[i]-> dwn = nil[i-1];
nil[i] -> dwn = nil[i-1];
}
head[i]->rgt = nil[i];
}
}
void SkipList::insert(int searchKey, int val)
{
vector <node*> preds = update(searchKey);
node* temp;
const int newLevel = randomLevel();
for(int i = 0; i< newLevel; i++)
{
node* ptr = makeNode(searchKey,val, newLevel-1);
temp = preds[i]->rgt;
preds[i]->rgt = ptr;
ptr->rgt = temp;
}
}
void SkipList::print() const{
node* list = head[0]->rgt;
int lineLength = 0;
std::cout<<"{";
while (list->rgt != nil[list->level])
{
std::cout<<"value: "<<list->data
<<", key: "<<list->key
<<", level: "<<list->level;
list = list->rgt;
if(list->rgt != nil[list->level]) std::cout<<" : ";
if (++lineLength % 2 == 0) std::cout << "\n";
}
std::cout << "}\n";
}
int SkipList::randomLevel() const{
int v = 1;
while (((double)std::rand() / RAND_MAX) < probability
&& v < maxLevel)
{
v++;
}
return v;
}
SkipList::node* SkipList::makeNode(int key, int value, int level){
return new node(key, value, level);
}
std::vector<SkipList::node*>SkipList::update(int searchKey) const{
int level = head[0]->level;
std::vector<node*> result(level,nullptr);
node* x ;
for(unsigned int i = level;i-- >0;)
{
x = head[i];
while(x->rgt->key < searchKey)
{
x = x->rgt;
}
result[i]= x;
}
return result;
}
int main()
{
SkipList s;
s.insert(5,22);
s.insert(2,33);
s.print();
return 0;
}
You should use push_back method in ctor of SkipList. Now you are creating objects
head[i] = new node(headkey,0,maxLevel-1);
and you are trying to assign the created node object to object returned by vector::operator[] which doesn't exist.
Or you can invoke vector::resize(maxlevel) method before entering into for loop.
I am implementing a skip list. The insertion function works fine and is able to print the list. But now I am trying to implement the "find" function and in this function I am getting a segmentation fault at the condition of while loop . When I debug the code , it works fine for all iterations except the last one. In the last iteration during condition check to enter in while loop it shows segmentation fault at this line precisely
while(x->rgt->key < searchKey)
I am not able to understand the reason because when I do handrun of the code everything seems fine. Please have a look and tell me what am I doing wrong ?
Also find function works fine if i search 1 and 2 but at 3 and 4 the fault occurs.
class SkipList
{
private:
struct node{
int key;
int data;
int level;
struct node* rgt = nullptr;
struct node* dwn = nullptr ;
node(int k, int value, int l):
key(k), data(value), level(l)
{}
};
//generates the ndde level in tha range [1,maxLevel).
int randomLevel() const;
//returns a set of pointers to the location at each node where new links are to be created
std::vector<node*> update(int searchKey) const ;
//creates a new node and returns a pointer to it
static node* makeNode(int key, int val, int level);
// Returns the first node for which node->key < searchKey is false
node* lower_bound(int searchKey) const;
const float probability;
const int maxLevel;
// head and tail vectors
vector<node*> head;
vector<node*> nil;
public:
SkipList();
// ~SkipList();
void insert(int searchKey, int val);
void find(int searchKey) const;
void erase(int searchKey);
void print() const;
};
SkipList::SkipList() :
probability(0.5), maxLevel(4)
{
head.resize(maxLevel, nullptr);
nil.resize(maxLevel,nullptr);
int headkey = std::numeric_limits<int>::min();
int nilkey = std::numeric_limits<int>::max();
for(int i = 0; i < maxLevel ;i++)
{
head[i] = new node(headkey,0,maxLevel-1);
nil[i] = new node(nilkey,0,maxLevel-1);
if(i>0)
{
head[i]->dwn = head[i-1];
nil[i] ->dwn = nil[i-1];
}
head[i]->rgt = nil[i];
}
}
void SkipList::find(int searchKey) const
{
node* x = head[maxLevel-1];
for(int i = maxLevel-1 ; i>= 0 ;i--)
{
while(x->rgt->key < searchKey)
{
x = x->rgt;
}
if(i != 0){x = x->dwn;}
}
if ((x->rgt->key == searchKey))
cout<<"Found"<<endl;
}
void SkipList::insert(int searchKey, int val)
{
vector <node*> preds = update(searchKey);
node* temp;
const int newLevel = randomLevel();
for(int i = 0; i< newLevel; i++)
{
node* ptr = makeNode(searchKey,val, newLevel-1);
temp = preds[i]->rgt;
preds[i]->rgt = ptr;
ptr->rgt = temp;
}
}
void SkipList::print() const
{
node *ptr = head[0]->rgt;
while(ptr->rgt != nullptr)
{
cout<<"Key: "<<ptr->key<<" Data: "<<ptr->data<<" Level: "<<ptr->level<<endl;
ptr = ptr->rgt;
}
}
int SkipList::randomLevel() const
{
int v = 1;
while (((double)std::rand() / RAND_MAX) < probability &&
v < maxLevel)
{
v++;
}
return v;
}
SkipList::node* SkipList::makeNode(int key, int value, int level)
{
return new node(key, value, level);
}
std::vector<SkipList::node*>SkipList::update(int searchKey) const
{
int level = head[0]->level;
std::vector<node*> result(level,nullptr);
node* x ;
for(unsigned int i = level;i-- >0;)
{
x = head[i];
while(x->rgt->key < searchKey)
{
x = x->rgt;
}
result[i]= x;
}
return result;
}
int main()
{
SkipList s;
int x,y;
for(int i = 1;i< 5;i++)
{
s.insert(i,i);
}
s.print();
cout<<endl;
s.find(3);
return 0;
}
A simple debug shows this in this loop:
while(x->rgt->key < searchKey)
{
x = x->rgt;
}
The value of x becomes NULL.
I am guessing that this is a case where you try to add an element at the end of the list.
If so, then you should come up with a different solution for this case.
For example:
while(x->rgt && x->rgt->key < searchKey)
{
x = x->rgt;
}
if (x->rgt)
{
// Use your original code
}
else
{
// Handle this special case
}
I have searched through the other questions and none of them seem to apply
exactly.
I am writing a program that finds a route through a maze,
the only real thing im having a problem with is this one compiler error.
It has to do with the one function I have the returns a Node ( struct).
Header file: (I cut the define stuff off)
#include <iostream>
#include <string>
using namespace std;
class Graph {
private:
struct Node {
int id; //int id
Node * north; //north path node
Node * south; //south path node
Node * east; //east path node
Node * west; //went path node
bool visited; // visited bool
};
//this struct holds the path that is found.
struct Elem {
int id; //The id of the node
string last; //the door that it passed through
Elem * back; //back one path
Elem * next; //forward one path
};
//This is a graph with a very smart struct
//This is the main node that makes up the graph.
Node * start;
Node ** initArr;
int arrLen;
Elem * head;
Elem * tail;
int path;
public:
Graph();
//Constructs empty graph
Graph(const Graph &v);
//copy constructor
~Graph();
//destructor
Graph & operator = (const Graph &v);
//assignment operator
void output(ostream & s) const;
//Prints the graph
void input(istream & s);
//input and creates the graph
Node * find(int id);
//finds the node in the graph
void makePath();
//makes a path through the maze
bool findPath(Node* cur, string room);
//worker function for recursion
void pathOut(ostream & s) const;
//Outputs the found path
void removeTail();
//Removes the last element
void addTail(Node* n, string door);
//Adds the element to the tail
//Mutators
void setId(Node* n ,int x);
void setVisited(Node* n, bool v);
//Elem Mutator
void seteId(Elem* e, int x);
//Elem Accessor
int geteId(Elem* e);
//Accessors
int getId(Node* n);
bool getVisited(Node* n);
};
And my actual code file.
#include <iostream>
#include "graph.h"
using namespace std;
//Constructs empty graph
Graph::Graph()
{
start = 0;
head = tail = 0;
path = 0;
}
//copy constructor
Graph::Graph(const Graph &v)
{
//not implemented
}
//destructor
Graph::~Graph()
{
for(int i = 0; i < arrLen + 1; i++)
{
delete initArr[i];
}
while(head != 0)
{
Elem* p = head;
head = head->next;
delete p;
}
delete[] initArr;
}
//assignment operator
Graph & Graph::operator = (const Graph &v)
{
//not implemented
}
//Prints the graph
void Graph::output(ostream & s) const
{
s<<"Node"<<'\t'<<"North"<<'\t'<<"East"<<'\t'<<"South"<<'\t'<<"West"<<'\n';
for(int i = 1; i < arrLen + 1; i++)
{
Node* temp = initArr[i];
s<<temp->id<<'\t';
if(temp->north != 0)
s<<temp->north->id<<'\t';
else
s<<"--"<<'\n';
if(temp->east != 0)
s<<temp->east->id<<'\t';
else
s<<"--"<<'\n';
if(temp->south != 0)
s<<temp->south->id<<'\t';
else
s<<"--"<<'\n';
if(temp->west != 0)
s<<temp->west->id<<'\t';
else
s<<"--"<<'\n';
s<<'\n';
}
}
//input and creates the graph
void Graph::input(istream & s)
{
int length = 0;
s>>length;
arrLen = length;
if(s)
{
//define array
initArr = new Node*[length + 1];
int temp = 0;
for(int i = 1; i < length + 1; i++)
{
//Create node
s>>temp;
Node* n = new Node;
n->id = temp;
n->visited = false;
//Add to array
initArr[i] = n;
}
//Make Exit Node
Node *x = new Node;
x->id = 0;
x->visited = false;
initArr[0] = x;
//Loop through all of the node input
int tn = 0;
for(int f = 0; f < length; f++)
{
//Set Pointers
s>>tn;
Node* curNode = find(tn);
int n = 0;
int e = 0;
int st = 0;
int w = 0;
s>>n>>e>>st>>w;
curNode->north = find( n );
curNode->east = find( e );
curNode->south = find( st );
curNode->west = find( w );
}
//set Entry point to graph
int last = 0;
s>>last;
start = find(last);
}
}
//finds the node in the array
Node* Graph::find(int id)
{
if( id == 0)
{
return initArr[0];
}
if(id == -1)
{
return 0;
}
else
{
for(int i = 1; i < arrLen + 1; i++)
{
if(initArr[i]->id == id)
{
return initArr[i];
}
}
cerr<<"NOT FOUND IN GRAPH";
return 0;
}
}
//makes a path through the maze
void Graph::makePath()
{
if(findPath(start->north, "north") == true)
{
path = 1;
return;
}
else if( findPath(start->east, "east") == true)
{
path = 1;
return;
}
else if( findPath(start->south, "south") == true)
{
path = 1;
return;
}
else if( findPath(start->west, "west") == true)
{
path = 1;
return;
}
return;
}
//finds a path to the outside
bool Graph::findPath(Node* cur, string room)
{
addTail(cur, room);
if(cur = initArr[0])
{
return true;
}
if(cur->north != 0 && cur->north->visited == false)
{
cur->visited = true;
findPath(cur->north, "north");
}
else if(cur->east != 0 && cur->east->visited == false)
{
cur->visited = true;
findPath(cur->north, "east");
}
else if(cur->south !=0 && cur->south->visited == false)
{
cur->visited = true;
findPath(cur->north, "south");
}
else if(cur->west != 0 && cur->west->visited == false)
{
cur->visited = true;
findPath(cur->north, "west");
}
else
{
cur->visited = false;
removeTail();
}
}
//Outputs the found path
void Graph::pathOut(ostream & s) const
{
if(path == 1)
{
Elem *p;
p = head->next;
while(p != 0)
{
s<<p->id<<"--> "<<p->last;
p= p->next;
}
}
else if(path == 0)
{
}
}
//Removes the last element in the chain
void Graph::removeTail()
{
Elem* temp = 0;
temp = tail;
tail = tail->back;
delete temp;
}
//Adds the element to the tail
void Graph::addTail(Node* n, string door)
{
if(head != 0)
{
Elem* temp = new Elem;
temp->id = n->id;
tail->next = temp;
tail->last = door;
temp->back = tail;
temp->next = 0;
tail = 0;
}
else
{
Elem *p = new Elem;
p->last = "";
p->back = 0;
p->next = 0;
head = p;
tail = p;
}
}
//Mutators
void Graph::setId(Node *n ,int x)
{
n->id = x;
}
void Graph::setVisited(Node *n, bool v)
{
n->visited = v;
}
//Elem Mutator
void Graph::seteId(Elem *e, int x)
{
e->id = x;
}
//Elem Accessor
int Graph::geteId(Elem *e)
{
return e->id;
}
//Accessors
int Graph::getId(Node *n)
{
return n-> id;
}
bool Graph::getVisited(Node *n)
{
return n->visited;
}
/*
//This is a graph with a very smart struct
//This is the main node that makes up the graph.
struct Node {
int id; //int id
Node *north; //north path node
Node *south; //south path node
Node *east; //east path node
Node *west; //went path node
bool visited; // visited bool
};
//this struct holds the path that is found.
struct Elem {
int id; //The id of the node
string last; //the door that it passed through
Elem* back; //back one path
Elem* next; //forward one path
};
Node* Start;
Node ** initArr;
Elem* head;
Elem* tail;
*/
//outputs using named operation
ostream & operator << (ostream &s, const Graph & v)
{
v.output(s);
return s;
}
The error is occurring on the find function.
In the cpp file, Node is not in global scope. It's nested inside Graph as such, you need to qualify it in a return type:
Graph::Node* Graph::find(int id){
// ...
}
Inside the function, you're in the scope of Graph again, as such you do not need to qualify it.
You have both Node and Element defined as structs inside the class Graph. It would be better to define them outside the class Graph. You can define a separate Node class and store the element struct as its private members. The error happens because Node is a private member of Graph, which can be accessed as Graph::Node. E.g. Graph::Node* find(...).
The following code got me really puzzled.
class
class AVLTree {
private:
struct AVLNode
{
AVLNode *leftchild;
AVLNode *rightchild;
int data;
int height;
};
AVLNode *root;
public:
AVLTree()
{
root = NULL;
}
bool isEmpty() const { return root == NULL; }
void print();
void inorder(AVLNode *n, int l);
void insert(int d);
void rotateLeft(AVLNode* n);
void rotateRight(AVLNode* n);
void rotateLeftTwice(AVLNode* n);
void rotateRightTwice(AVLNode* n);
AVLTree::AVLNode* insert(int d, AVLNode* n);
int max( int a, int b);
int height( AVLNode* n); };
insert function.
AVLTree::AVLNode* AVLTree::insert(int d,AVLNode *n){
if (n == NULL)
{
AVLNode *n = new AVLNode;
n->data = d;
n->leftchild = NULL;
n->rightchild = NULL;
n->height = 0;
} else if( d < n->data) {
n->leftchild = insert(d,n->leftchild);
} else if (d > n->data) {
n->rightchild = insert(d,n->rightchild);
}
else {
n->height = max(height(n->leftchild), height(n->rightchild));
return n;
}
-----> This section of the code gives be "EXC_BAD_ACCESS".
n->height = max(height(n->leftchild), height(n->rightchild));
return n;
}
This is the height function.
int AVLTree::height(AVLNode* node)
{ cout << "HEIGHT";
if(node == NULL)
{
return -1;
}
else {
return node->height;
}
}
Anyone knows why?
=== Update:
when doing the rotation
void AVLTree::rotateLeft(AVLNode* n)
{
AVLNode *child = n->leftchild;
n->leftchild = child->rightchild;
child->rightchild = n;
n->height = max(height(n->leftchild),height(n->rightchild))+1;
child->height = max(height(child->leftchild),height(child->rightchild))+1;
n = child;
}
It seems not to be swapping values as it should. While n = child seems to swap locally it does not reflect a change i the rest of the code. Giving me an infinite loop.
If n was null on entry to the function, then that line will attempt to dereference it, giving the error. Your code to allocate a new node should assign it to n itself, rather than a separate variable with the same name that shadows the function argument.
Change the first line of the if (n == NULL) block from
AVLNode *n = new AVLNode;
to
n = new AVLNode;
Regarding the update: In your rotate function, n is a local (automatic) variable, and changing that won't affect anything outside the function. You will need to either pass the pointer by reference, or return the new pointer value (like you do in insert()).