C++ Priority Queue crashes when I insert elements - c++

I made up a priority-queue through a Min Heap.
This is a PriorityQueue of pointers to the class Node.
When I try to create a PriorityQueue object trough the vector it works great. The problem is inserting the pointers to Node individually through Insert method. It also works and prints the priority-queue but sometimes it crashes at the end of the execution! It returns an error despite works good.
Output:
a 1
b 2
c 3
Process returned -1073741819 (0xC0000005) execution time : 3.000 s
Press any key to continue.
Main:
int main()
{
NODE a = new Node('a',1);
NODE b = new Node('b',2);
NODE c = new Node('c',3);
Q.Insert(a);
Q.Insert(b);
Q.Insert(c);
Q.Print();
return 0;
}
Node code:
typedef class Node *NODE;
class Node {
private:
unsigned char Ch;
int Key;
NODE L;
NODE R;
public:
Node() { L = NULL; R = NULL; };
Node(int, unsigned char, NODE, NODE);
Node(unsigned char, int);
~Node() { delete L; delete R; };
NODE Left();
NODE Right();
int GetKey();
unsigned char GetChar();
void SetKey(int);
void SetChar(unsigned char);
};
Node::Node(unsigned char c, int k)
{
Ch = c; Key = k; R = NULL; L = NULL;
}
NODE Node::Left()
{
return L;
}
NODE Node::Right()
{
return R;
}
unsigned char Node::GetChar()
{
return Ch;
}
int Node::GetKey()
{
return Key;
}
void Node::SetKey(int k)
{
Key = k;
}
PriorityQueue code:
class PriorityQueue {
private:
vector<NODE> A;
int Heap_Size;
int Parent(int);
int Left(int);
int Right(int);
void Swap(NODE &, NODE &);
void MinHeapify(int);
public:
PriorityQueue();
PriorityQueue(vector<NODE>);
~PriorityQueue() {};
NODE Minimum();
NODE ExtractMin();
void DecreaseKey(int, int);
void Insert(NODE);
bool IsEmpty();
void Print();
};
PriorityQueue::PriorityQueue()
{
// I need to push back an empty node to use the vector from the index 1.
// This is important to move in the min-heap trough the indices.
NODE Default = new Node;
A.push_back(Default);
Heap_Size = 0;
}
PriorityQueue::PriorityQueue(vector<NODE> vett)
{
A = vett; Heap_Size = A.size()-1;
for (int i=Heap_Size/2; i>=1; i--)
{
MinHeapify(i);
}
}
void PriorityQueue::Swap(NODE &a, NODE &b)
{
NODE temp = a;
a = b;
b = temp;
}
void PriorityQueue::DecreaseKey(int i, int key)
{
if (key > A[i]->GetKey())
{
cout << "How can I decrease the key?" << endl;
return;
}
A[i]->SetKey(key);
while (i>1 && A[Parent(i)]->GetKey() > A[i]->GetKey())
{
Swap(A[i],A[Parent(i)]);
i = Parent(i);
}
}
void PriorityQueue::Insert(NODE Nodo)
{
Heap_Size++;
A[Heap_Size] = Nodo;
DecreaseKey(Heap_Size,Nodo->GetKey());
}
void PriorityQueue::Print()
{
for (int i=1; i<=Heap_Size; i++)
cout << A[i]->GetChar() << " " << A[i]->GetKey() << endl;
}
Thank you very much!!!!

I solved it! The problem was:
Heap_Size++;
A[Heap_Size] = Nodo;
A is a vector, so I had to edit in this way:
A.push_back(Nodo);

Related

Singly Linked List using Arrays: It's crashing on run-time

Whats wrong with this code?
I am writing this code to implement singly linked list using arrays but its not working. Im using code::blocks and its crashing on run time. Please help.
I must have missed out on something when it was taught in the class. xD
#include<iostream>
#include<stdio.h>
using namespace std;
class Node
{
int data;
Node *next;
public:
Node(int n)
{
data=n;
next=NULL;
}
friend class List;
};
class List
{
Node *listptr;
public:
void create();
void display();
};
void List::create()
{
Node *temp;
int n, num;
cout << "Enter number of nodes:" << endl;
cin >> n;
cout << "/nEnter the data" << endl;
for(int i=0; i<n; i++)
{
cin >> num;
Node *new_node=new Node(num);
if(listptr==NULL)
listptr=temp=new_node;
else
{
temp->next=new_node;
temp=temp->next;
}
}
}
void List::display()
{
Node *temp=listptr;
while(temp!=NULL)
{
cout << temp->data << "->";
temp=temp->next;
}
}
main()
{
List l1;
l1.create();
l1.display();
}
listptr not initialized, you can initialize in constructor.
List() {
listptr = 0;
}
Class List should be
class List
{
Node *listptr;
public:
List() {
listptr = 0;
}
void create();
void display();
};
Try following piece of code -
First Creating Node
class ListElement
{
int data;
ListElement* next;
public:
void set_element(int item) { data = item; }
int get_value() { return data; }
friend class List;
};
Another class for further operation
class List
{
ListElement *Start, *Tail, *New;
public:
List() { Start = Tail = New = NULL; } // initialise all pointer value to NULL
void add_element(int element) {
// Create a new Node
New = new ListElement;
New->set_element(element);
New->next = NULL;
// adding value or linkig each node to each other
(Start == NULL) ? Start = New : Tail->next = New;
Tail = New;
}
// print the whole linked list
void print()
{
ListElement* Current = Start;
while (Current != NULL)
{
cout << Current->get_value() << endl;
Current = Current->next;
}
}
};
Main Function
int main()
{
List L;
int num_of_element, element;
cin >> num_of_element;
for (int i(0); i < num_of_element; i++) {
cin >> element;
L.add_element(element);
}
L.print();
}
Hope it'll work.

Skip List implementation in cpp

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.

Segmentation fault in skip list

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
}

How to find the invalid pointer in a C++ tree program?

My program is simple, make a tree (min heap), and through a inorder traversal to store data to an array, then destroy the tree (heap).
When I run to the store step, the program crash. I can't find why, even I know the bug position (I comment some code and run to see whether it works and finally I find the bug position)
I think maybe I delete a invalid pointer, but I can't find where; please help me to find it.
When I input
6
1 2 3 4 5 6
it works
when I input
8
90 80 30 40 10 45 20 50
then crash.
I don't know what different between this two group numbers
#include <iostream>
typedef int ElementType;
struct BTree
{
ElementType data;
BTree *Left;
BTree *Right;
};
class BuildingMinHeap
{
ElementType *Elements;
int Size;
int Capacity;
BTree *root;
ElementType *inorder_array; // to store members inorderly
public:
BuildingMinHeap(int MaxSize, ElementType MinData): Size(0), Capacity(MaxSize+1)
{
Elements = new ElementType[MaxSize+1];
Elements[0] = MinData; // sentinel
root = NULL;
inorder_array = new ElementType[Size];
}
~BuildingMinHeap()
{
if (Elements)
delete [] Elements;
if (inorder_array)
delete [] inorder_array;
if (root != NULL)
DeleteBTree(root);
}
void Insert(ElementType item);
void genBTree(ElementType *a, int position); // call CreateBTree()
void ModifyArray(ElementType *input, int size); // call gen_inorder_array()
ElementType *getElements() {return Elements;}
BTree *getRoot() {return root;}
void DeleteBTree(BTree *root);
private:
BTree *CreateBTree(ElementType *a, int position);
void gen_inorder_array(const BTree *node);
};
void BuildingMinHeap::Insert(ElementType item)
{
int i;
i = ++Size;
for (; Elements[i/2] > item; i /= 2)
{
// Elements[0] is sentinel
Elements[i] = Elements[i/2];
}
Elements[i] = item;
}
BTree *BuildingMinHeap::CreateBTree(ElementType *a, int position) // array to Binary Tree list
{
BTree *new_node = new BTree;
if (position > Size)
return NULL;
new_node->data = a[position];
new_node->Left = CreateBTree(a, 2*position);
new_node->Right = CreateBTree(a, 2*position+1);
return new_node;
}
void BuildingMinHeap::genBTree(ElementType *a, int position) // call CreateBTree()
{
root = CreateBTree(a, position);
}
void BuildingMinHeap::DeleteBTree(BTree *root)
{
if (root == NULL)
return;
DeleteBTree(root->Left);
DeleteBTree(root->Right);
delete root;
root = NULL;
return;
}
void BuildingMinHeap::gen_inorder_array(const BTree *node) // to generate members of tree root inorderly
{
static int index = 0;
// like print inorder tree
if (node)
{
gen_inorder_array(node->Left);
inorder_array[index++] = node->data;
// std::cout << node->data << " ";
gen_inorder_array(node->Right);
}
}
void BuildingMinHeap::ModifyArray(int *input, int size) // call gen_inorder_array()
{
gen_inorder_array(root); // generate inorder_array, when I comment this line, it work
// below commented code is nothing about tree root member
//
// // generate<elements of inorder_array,elements' address of Elements> map
// std::map<int, int*> inorder_Ele_map;
// for (int i = 0; i != Size; i++)
// {
// ElementType *it = std::find(Elements+1, Elements+Size, *(inorder_array+i));
// inorder_Ele_map[*(inorder_array+i)] = Elements + (it-Elements);
// }
//
//
// // change Elements array according input array
// for (int i = 0; i != size; i++)
// {
// if (*(inorder_array+i) != *(input+i))
// {
// *(inorder_Ele_map[*(inorder_array+i)]) = *(input+i);
// }
// }
}
int main(void)
{
int n;
std::cin >> n;
int *input = new int[n];
for (int i = 0; i != n; i++)
std::cin >> input[i];
BuildingMinHeap h(n, -999); // empty heap;
for (int i = 0; i != n; i++)
h.Insert(input[i]); // insert element to heap
h.genBTree(h.getElements(), 1); // generate Binary Tree(pointer) from Elements array, index 1 begin
// so far it work
h.ModifyArray(input, n); // if I comment this line, it would work
h.DeleteBTree(h.getRoot()); // I have already do call this function in destructor,
// but in destructor I call it when root != NULL,
// I have no idea when I comment this line, there are a crash.
delete [] input;
return 0;
}

SIGSEGV error with BFS Algorithm

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.