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;
}
Related
I have to implement a HashTable with linked lists. It is almost done (still missing templates, will do in time), but I'm stuck at something.
Basically, I want to resize my hashtable when the load factor reaches a given value, say 50%. But I don't know how I should do it.
I have a basic idea:
Create a temporary HT with the new size
Hash every data in every list from the old HT to the temporary one
Delete the old HT
Return the temporary HT
I can't figure out an implementation for it though...
Here is what I have so far:
//List:
struct Node
{
string data;
Node *next;
};
class List
{
private:
Node *head, *tail;
int length;
friend class HashTable;
public:
List();
List(const List &L);
//~List() {delete this;};
List& operator =(List L);
int find(string);
void insert(string value);
void remove_head();
void remove_poz(int);
void remove_tail();
void clear();
void display();
};
List::List()
{
head = NULL;
tail = NULL;
length = 0;
}
List::List(const List& L)
{
Node** temp = &head;
const Node* source = L.head;
while(source)
{
*temp = new Node(*source);
temp = &(*temp)->next;
source = source->next;
}
}
List& List::operator =(List L)
{
swap(head, L.head);
return *this;
}
void List::insert(string value)
{
Node* temp = new Node;
temp->data = value;
temp->next = NULL;
if (!head)
head = temp;
if (tail)
tail->next = temp;
tail = temp;
length++;
}
void List::display()
{
Node *temp = new Node;
temp = head;
while (temp != NULL)
{
cout<<temp->data<<" ";
temp = temp->next;
}
delete temp;
}
//HashTable:
class HashTable
{
private:
List *table;
float load, stored;
int slots;
friend class List;
public:
HashTable();
HashTable(int);
~HashTable();
int hashFunc(string key);
int findTable(string);
int findList(string);
HashTable& operator =(const HashTable&);
void resize(); //I need this one
void insert(string);
void remove(string);
void clear(int);
void clear();
void display();
};
HashTable::HashTable()
{
stored = 0;
load = 0.00;
slots = 15;
table = new List[slots];
}
HashTable::HashTable(int size)
{
stored = 0;
load = 0.00;
slots = size;
table = new List[slots];
}
int HashTable::hashFunc(string key)
{
unsigned int i, ind = 0;
for (i = 0; i<key.length(); ++i)
ind = ind + key[i];
ind %= slots;
return ind;
}
HashTable& HashTable::operator =(const HashTable& T) //I suppose it is incorrect
{
int i;
HashTable temp(T.slots);
for (i = 0; i < slots; ++i)
{
temp.table[i] = T.table[i];
}
return temp;
}
void HashTable::insert(string value)
{
int ind = hashFunc(value);
table[ind].insert(value);
if (!table[ind].head->next) stored++;
load = stored / slots;
if (load > 0.50) resize();
}
(Note: only the functions that might be needed are shown here)
Any help, correction or suggestion would be much appreciated :)
UPDATE:
Managed to pull this one off:
void HashTable::resize()
{
int i;
int newSize = slots * 2;
int newLoad = stored / newSize;
HashTable HT(newSize);
Node* temp;
for (i = 0; i < slots; ++i)
{
temp = table[i].head;
while (temp != NULL)
{
HT.insert(temp->data);
temp = temp->next;
}
}
}
Now I have a new HashTable named HT, with double the size of the original one, and all elements have been inserted correctly.
But I don`t know how to proceed.
The easiest way to proceed is to add a swapContents() method to your HashTable class:
void HashTable::swapContents(HashTable & rhs)
{
std::swap(table, rhs.table);
std::swap(load, rhs.load);
std::swap(stored, rhs.stored);
std::swap(slots, rhs.slots);
// any other member-variables of the HashTable class would get swapped here too
}
... then call swapContents(HT) at the end of your resize() method, so that HT becomes the older/smaller HashTable (and gets discarded) while this becomes the newer/larger table.
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 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.
I'm having some trouble creating a copy constructor for my hash map class right now. Currently, I understand how to do a copy constructor for arrays, by copying things over from the original array to the next. For example, here is what would be done for an array list:
ArrayList::ArrayList(const ArrayList& a)
: items{new std::string[a.cap]}, sz{a.sz}, cap{a.cap}
{
// arrayCopy is a for loop that does items[i] = a.items[i] on each iteration
arrayCopy(items, a.items, sz);
}
I understand that we need to initialize values to a new array list, and copy them over to a new list of arrays. However, I'm having trouble wrapping my mind around doing this to a separately chained hash map.
In my HashMap.hpp file, I have an unmodifiable structure, like this:
struct Node
{
std::string key;
std::string value;
Node* next;
};
I need help understanding how to put each node into my copy constructor. This is my copy constructor, without the actual "copying" code:
HashMap::HashMap(const HashMap& hm)
: hashTable{new Node*[hm.amountOfBuckets]}, amountOfBuckets{hm.amountOfBuckets}, sz{hm.sz}
{
}
How would I accomplish properly iterating through each hash table index, and creating a new node depending on how many there are in the original table? Would I have to create four Nodes, two to keep track of the new table, and two to keep track of the original table?
I tried to implement this and also tried to implement a way to copy over values within a do while loop. This is my code (that doesn't work and completely sucks :( )
for(unsigned int i = 0; i < amountOfBuckets; i++) {
// target
Node* newHead = hashTable[i];
Node* newCurrent = newHead;
// source
Node* head = hm.hashTable[i];
Node* current = head;
do{
newCurrent = new Node();
newCurrent->key = current->key;
newCurrent->value = current->value;
newCurrent->next = current->next;
newCurrent = hashTable[i];
} while(newCurrent != nullptr);
With this I run into segmentation faults. I'm really not quite sure how to properly copy over each value into the new hash table? Or how I should go about linking it all together?
Here is the declarations for HashMap.hpp
#ifndef HASHMAP_HPP
#define HASHMAP_HPP
#include <functional>
#include <string>
class HashMap
{
public:
typedef std::function<unsigned int(const std::string&)> HashFunction;
static constexpr unsigned int initialBucketCount = 10;
public:
HashMap();
// This constructor instead initializes the HashMap to use a particular
// hash function instead of the default
HashMap(HashFunction hasher);
HashMap(const HashMap& hm);
~HashMap();
HashMap& operator=(const HashMap& hm);
void add(const std::string& key, const std::string& value);
void remove(const std::string& key);
bool contains(const std::string& key) const;
std::string value(const std::string& key) const;
unsigned int size() const;
unsigned int bucketCount() const;
double loadFactor() const;
unsigned int maxBucketSize() const;
private:
// This structure describes the nodes that make up the linked lists in
// each of this HashMap's buckets.
struct Node
{
std::string key;
std::string value;
Node* next;
};
// hash function gets stored in here
HashFunction hasher;
private:
Node** hashTable;
unsigned int amountOfBuckets;
unsigned int sz;
public:
unsigned int getTableIndex(unsigned int hashVal) const;
};
And here is my (incomplete) code for HashMap.cpp. Also, I will not be using the hash function currently in the namespace. I just used it as an easy way to predict bucket indices to test my add/remove functions.
#include <iostream>
#include "HashMap.hpp"
namespace {
unsigned int easyHashFunc(const std::string& key) {
unsigned int hashValue = 0;
for(int i = 0; i < key.length(); i++) {
int letterIndex = key.at(i);
hashValue += letterIndex; // just add up the letters
} // end for
return hashValue;
} // end easyHashFunc
}
HashMap::HashMap()
: hasher{easyHashFunc}, hashTable{new Node*[initialBucketCount]()}, amountOfBuckets{initialBucketCount}, sz{0}
{
}
// constructor that initializes HashMap to use a different hash function other
// than the default
HashMap::HashMap(HashFunction hasher)
: hasher{hasher}, hashTable{new Node*[initialBucketCount]()}, amountOfBuckets{initialBucketCount}, sz{0}
{
}
HashMap::HashMap(const HashMap& hm)
: hashTable{new Node*[hm.amountOfBuckets]}, amountOfBuckets{hm.amountOfBuckets}, sz{hm.sz}
{
for(unsigned int i = 0; i < amountOfBuckets; i++) {
Node* newHead = hashTable[i];
Node* newCurrent = newHead;
// source
Node* head = hm.hashTable[i];
Node* current = head;
do{
newCurrent = new Node();
newCurrent->key = current->key;
newCurrent->value = current->value;
newCurrent->next = current->next;
newCurrent = hashTable[i];
} while(newCurrent != nullptr);
}
}
// destructor: deallocate the HashMap
HashMap::~HashMap()
{
for(unsigned int i = 0; i < amountOfBuckets; i++) {
Node* nextNode = hashTable[i]; // store each hashtable list in a bucket node
while(nextNode != nullptr) {
Node* deleteCurrent = nextNode; // set current to the bucket node (head)
nextNode = nextNode->next; // delete current is on the first node, update head to second node
delete deleteCurrent;
} // end while
} // end for
// once done, delete hash table
delete[] hashTable;
} // end destructor
// Assignment operator that overloads equals
HashMap& HashMap::operator=(const HashMap& hm)
{
// incomplete
return *this;
}
void HashMap::add(const std::string& key, const std::string& value)
{
// Check if key being stored matches key already in hashmap
unsigned int hashedValue = hasher(key); // get hash value (unmodified by buckets)
unsigned int tableIndex = getTableIndex(hashedValue); // get the table index
// case 1, check to see if current is nullptr, meaning our first node
// is the one we should use, ie. we don't need to traverse the list
if(contains(key) == true) { // if key is already in the hashtable
return; // exit program
} else { // otherwise, key is not in the hash table
Node* head = hashTable[tableIndex];
Node* current = head;
if(current == nullptr) {
// nothing in bucket
// create a new node
current = new Node();
current->key = key; // set username
current->value = value; // set pw
current->next = nullptr;
hashTable[tableIndex] = current;
return; // exit
} else {
do {
current = current->next; // advance to next node
}while(current != nullptr);// end while
// currently at node we want to insert key/value at
current = new Node();
current->key = key; // set key(username)
current->value = value; // set value (pw)
current->next = head;
hashTable[tableIndex] = current; // set next to point to nullptr
} // end inner if-else (creates node)
} // end outer if-else
} // end add
// takes in a key (username), removes it and the value (password) associated
// with it, otherwise, it has no effect
void HashMap::remove(const std::string& key)
{
unsigned int hashedValue = hasher(key);
unsigned int tableIndex = getTableIndex(hashedValue);
if(contains(key) == false) { // could not find key in bucket
return; // do nothing
} else {
Node* prevNode = hashTable[tableIndex];
Node* delNode = prevNode;
if(prevNode->key == key) { // first one is a match
hashTable[tableIndex] = prevNode->next; // set the head of the hash table to point to the next node
delete delNode;
return; // exit
} else { // otherwise, we must loop through and find the node we want to delete
do{
// check for match, if found, break out of do while
if(delNode->key == key) {
break;
}
prevNode = delNode; // save current node in previous
delNode = delNode->next; // point the searched node to the next node
}while(delNode != nullptr); // end do while
// set the previous node to point to delNodes next node
prevNode->next = delNode->next;
} // end inner if-else
delete delNode; // de-allocate
} // end outer if-else
} // end remove()
// returns true if given key is in hash map, otherwise returns false
// this acts as a find method
bool HashMap::contains(const std::string& key) const
{
unsigned int hashedValue = hasher(key); // hash the key given to get an index
unsigned int tableIndex = getTableIndex(hashedValue); // get the table index
Node* current = hashTable[tableIndex];
// iterate through each node in the linked list
// start at first node (this is current)
while(current != nullptr) {
if(current->key == key) {
return true; // found match, exit
}
current = current->next;
} // end while
return false; // we haven't found a match
}
// value() returns the value associated with the given key in this HashMap
// if the key is stored in this HashMap; if not, the empty string is returned.
std::string HashMap::value(const std::string& key) const
{
if(contains(key) == true) { // found match
unsigned int hashedValue = hasher(key); // hash the key given to get an index
unsigned int tableIndex = getTableIndex(hashedValue); // get the table index
Node* current = hashTable[tableIndex];
while(current != nullptr && current->key != key) {
current = current->next;
}
return current->value; // return value after traversal
} else {
return ""; // no match, return empty string
}
}
unsigned int HashMap::size() const
{
return sz;
}
unsigned int HashMap::bucketCount() const
{
return amountOfBuckets;
}
double HashMap::loadFactor() const
{
return sz / amountOfBuckets;
}
// return the table index for a given hashvalue
unsigned int HashMap::getTableIndex(unsigned int hashVal) const {
return hashVal % amountOfBuckets;
}
HashMap::HashMap(const HashMap& hm)
{
amountOfBuckets=hm.amountOfBuckets;
hashTable= new Node* [amountOfBuckets];
for (int i=0; i<amountOfBuckets; i++)
{
Node* n = hm.hashTable[i];
Node** p = &hashTable[i];
*p = NULL;
while (n)
{
Node* c = new Node(*n); // node copy constructor, should set n->next to null
*p = c;
p=&c->next;
n=n->next;
}
}
}
If you don't want Node copy constructor replace Node* c = new Node(*n); with:
Node* c = new Node;
c->key = n->key;
c->value = n->value;
c->next = NULL;
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);