c++ - overload [] operator for Red-Black Tree - c++

I'm trying to overload [] for red-black tree. Each node contains four elements: key, gender, height and weight. "key" value will be randomly assigned and should be unique, so I want to overload [] by traversing each node to see if the "key" value already exists. However, it worked only when there was just one node. Here's the code:
#include<iostream>
#include<string>
using namespace std;
enum COLOR { RED, BLACK };
class Node
{
public:
Node(int key, string gender, int height, int weight, const COLOR & color = RED)
:pLeft(NULL), pRight(NULL), pParent(NULL), key(key), gender(gender), height(height), weight(weight), color(color)
{}
~Node();
string getGender();
int getHeight();
int getWeight();
Node* pLeft;
Node* pRight;
Node* pParent;
int key;
string gender;
int height;
int weight;
COLOR color;
};
class RBTree
{
public:
RBTree() :pRoot(NULL) {}
Node &operator[](int key);
bool insert(int key, string gender, int height, int weight);
void RotateL(Node* parent);
void RotateR(Node* parent);
void InOrder();
void InOrder(Node* pRoot);
Node* searchTree(Node* pRoot, int key);
bool CheckRBTree();
bool CheckRBTree(Node* pRoot,int counter,int k);
private:
Node* pRoot;
};
string Node::getGender()
{
return gender;
}
int Node::getHeight()
{
return height;
}
int Node::getWeight()
{
return weight;
}
Node &RBTree::operator[](int key)
{
Node* ptr = searchTree(pRoot, key);
return *ptr;
}
bool RBTree::insert(int key, string gender, int height, int weight)
{
// create root
if (pRoot == NULL)
{
pRoot = new Node(key, gender, height, weight);
pRoot->color = BLACK;
return true;
}
// find loc to insert
Node* pCur = pRoot;
Node* parent = NULL;
while (pCur)
{
if (key < pCur->key)
{
parent = pCur;
pCur = pCur->pLeft;
}
else if (key > pCur->key)
{
parent = pCur;
pCur = pCur->pRight;
}
else
return false;
}
// insert
pCur = new Node(key, gender, height, weight);
if (key < parent->key)
parent->pLeft = pCur;
else
parent->pRight = pCur;
pCur->pParent = parent;
// discuss 3 cases
while (pRoot != pCur&&pCur->pParent->color == RED)
{
Node* gf = parent->pParent;
if (gf->pLeft == parent)
{
Node* uncle = gf->pRight;
if (uncle&&uncle->color == RED)
{
parent->color = BLACK;
uncle->color = BLACK;
gf->color = RED;
pCur = gf;
parent = pCur->pParent;
}
else // turn case 3 into case 2
{
if (parent->pRight == pCur)
{
RotateL(parent);
std::swap(parent, pCur);
}
gf->color = RED;
parent->color = BLACK;
RotateR(gf);
}
}
else
{
Node*uncle = gf->pLeft;
if (uncle && uncle->color == RED) //case 1
{
parent->color = BLACK;
uncle->color = BLACK;
gf->color = RED;
pCur = gf;
parent = pCur->pParent;
}
else // turn case 3 into case 2
{
if (parent->pLeft == pCur)
{
RotateR(parent);
std::swap(parent, pCur);
}
gf->color = RED;
parent->color = BLACK;
RotateL(gf);
}
}
}
pRoot->color = BLACK;
return true;
}
// rotate left
void RBTree::RotateL(Node* parent)
{
Node* subR = parent->pRight;
Node* subRL = subR->pLeft;
parent->pRight = subRL;
if (subRL)
subRL->pParent = parent;
subR->pLeft = parent;
Node* gparent = parent->pParent;
parent->pParent = subR;
subR->pParent = gparent;
if (gparent == NULL)
pRoot = subR;
else if (gparent->pLeft == parent)
gparent->pLeft = subR;
else
gparent->pRight = subR;
}
void RBTree::RotateR(Node* parent)
{
Node* subL = parent->pLeft;
Node* subLR = subL->pRight;
parent->pLeft = subLR;
if (subLR)
subLR->pParent = parent;
subL->pRight = parent;
Node* gparent = parent->pParent;
parent->pParent = subL;
subL->pParent = gparent;
if (gparent == NULL)
pRoot = subL;
else if (gparent->pLeft == parent)
gparent->pLeft = subL;
else
gparent->pRight = subL;
}
void RBTree::InOrder()
{
cout << "InOrder: ";
InOrder(pRoot);
cout << endl;
}
void RBTree::InOrder(Node* pRoot)
{
if (pRoot)
{
InOrder(pRoot->pLeft);
cout << pRoot->key << " ";
InOrder(pRoot->pRight);
}
}
Node* RBTree::searchTree(Node* pRoot, int key)
{
if(pRoot->key == key)
return pRoot;
if(pRoot)
{
cout << "current node is " << pRoot->key << endl;
searchTree(pRoot->pLeft, key);
searchTree(pRoot->pRight, key);
}
return NULL;
}
bool RBTree::CheckRBTree()
{
if (pRoot == NULL)
return true;
if (pRoot->color == RED)
return false;
int blackcount = 0;
Node* pCur = pRoot;
while (pCur)
{
if (pCur->color == BLACK)
blackcount++;
pCur = pCur->pLeft;
}
return CheckRBTree(pRoot, blackcount, 0);
}
bool RBTree::CheckRBTree(Node* pRoot, int counter, int k)
{
if (pRoot == NULL)
return true;
if (pRoot->color == BLACK)
k++;
Node* parent = pRoot->pParent;
if (parent && parent->color == RED && pRoot->color == RED)
return false;
if (pRoot == NULL)
{
if (k != counter)
return false;
}
return CheckRBTree(pRoot->pLeft, counter, k)
&& CheckRBTree(pRoot->pRight, counter, k);
}
int main()
{
int a[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };
RBTree t;
for (int index = 0; index < sizeof(a) / sizeof(a[0]); index++)
{
cout << a[index] << " ";
t.insert(a[index], "male", 12, 3);
}
cout << endl;
cout << t[7].getGender() << endl;
return 0;
}
Anyone knows how to fix this? Thanks in advance.

You didn't implement searchTree yet it seems.
Node* RBTree::searchTree(Node* pRoot, int key)
{
if(pRoot->key == key)
return pRoot;
if(pRoot)
{
cout << "current node is " << pRoot->key << endl;
searchTree(pRoot->pLeft, key);
searchTree(pRoot->pRight, key);
}
return NULL;
}
You return the root if it matches and all other cases return NULL. That can't work.
Note: You use pRoot->key and only after that check if(pRoot). If pRoot is NULL you already crashed there.

Related

how to insert nodes in red black tree node?

I had found this implementation in [github][1], i made some changes like adding a 2nd value to the node, and using each left and right node as a pointer Node the problem with the tree it is and whenever inserting nodes then searching in the nodes in the tree it only iterates through the tree from first to last pointers when using TMapFind which calls the function pointer TMapNodeComparison_F to compare pointers. I wonder what could be causing this bug I suspect it's something in the logic of TMapInsertNode checking if a node is black/red?
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#define ASSERT_NOT_NULL(x) if(x)
#define ASSERT_NULL(x) if(x ==NULL)
#define ASSERT_NULL_(x,y) if(x== NULL && y==NULL)
typedef struct CByte
{
unsigned char* value;
size_t index;
size_t length;
}BYTES;
//struct Data;
struct Node;
struct TMap;
struct Node
{
CByte* value;
size_t index;
struct Node* Left;
struct Node* Right;
struct Node* Parent;
bool color;
};
typedef int (*TMapNodeComparison_F) (struct TMap* map, struct Node* a, struct Node* b);
typedef void (*TMapNode_F) (struct TMap* map, struct Node* node);
struct TMap
{
struct Node* root;
size_t TSize;
TMapNodeComparison_F compareNodeFunction;
};
struct Node* TMapNodeAlloc()
{
return (Node*)malloc(sizeof(Node));
}
struct Node* TMapNodeCalloc()
{
return (Node*)calloc(1,sizeof(Node));
}
struct Node* TMapInitializationNodeTree(struct Node* node,struct CByte* _data)
{
ASSERT_NOT_NULL (node)
{
node->value = _data;
std::string s = reinterpret_cast<char const*>(_data->value);
std::cout << s << std::endl;
node->color = 1;//Initialize as Black
node->Left = node->Right = NULL;
node->index = _data->index;
}
return node;
}
struct Node* TMapInitializationCreateNode(CByte* _data)
{
return TMapInitializationNodeTree(TMapNodeAlloc(), _data);
}
void TMapNodeDeAlloc(struct Node* node)
{
ASSERT_NOT_NULL(node)
free(node);
}
int AreNodesRed(struct Node* nodeA, struct Node* nodeB)
{
return (nodeA && nodeB) ? !nodeA->color && !nodeB->color : 0;
}
static bool TMapIsNodeBlack (struct Node* node)
{
return node ? node->color == 1 : false;
}
static bool TMapIsNodeRed(struct Node* node)
{
return node ? !node->color : false;
}
static bool TMapAreNodesBlack(struct Node* nodeA,struct Node* nodeB)
{
return nodeA && nodeB ? nodeA->color == 1 && nodeB->color ==1 : false;
}
static struct Node* TMapNodeRotateL(struct TMap* map,struct Node* node , int side)
{
struct Node* blackNode = NULL;
ASSERT_NOT_NULL (node)
{
blackNode = !side == 0 ? node->Left : node->Right;
/* blackNode->Left = blackNode->Right = (Node*)calloc(1, sizeof(Node));*/
!side == 0 ? node->Left : node->Right = side == 0 ? blackNode->Left : blackNode->Right;
node->color = 0; //Red
blackNode->color = 1;//Black
side == 0 ? blackNode->Left : blackNode->Right = node;
node->Parent = blackNode;
}
return blackNode;
}
static struct Node* TMapNodeRotateR(TMap* map,struct Node* node,int side)
{
struct Node* rightNode = NULL;
ASSERT_NULL(node)
{
!side ==0 ? node->Left :node->Right = TMapNodeRotateL(map,!side == 0 ? node->Left : node->Right,!side);
rightNode = TMapNodeRotateL(map,node,side);
}
return rightNode;
}
int TMapNodeComparison(struct TMap* map, struct Node* a, struct Node* b)
{
return (a->value > b->value) - (a->value < b->value);
}
void TMapNodeDealloc(struct TMap* map, struct Node* node)
{
ASSERT_NOT_NULL (map)
{
ASSERT_NOT_NULL (node)
{
TMapNodeDeAlloc(node);
}
}
}
struct TMap* TMapAlloc()
{
return (TMap*)malloc(sizeof(TMap));
}
struct TMap* TMapInitialize(struct TMap* map, TMapNodeComparison_F node_cmp_cb)
{
ASSERT_NOT_NULL (map)
{
map->root = NULL;
map->TSize = 0;
map->compareNodeFunction = node_cmp_cb ? node_cmp_cb : TMapNodeComparison;
}
return map;
}
struct TMap* TMapCreate(TMapNodeComparison_F node_cb)
{
return TMapInitialize(TMapAlloc(), node_cb);
}
void TMapDealloc(struct TMap* map, TMapNode_F node_cb)
{
ASSERT_NOT_NULL(map)
{
ASSERT_NOT_NULL(node_cb)
{
struct Node* node = map->root;
struct Node* save = NULL;
while (node)
{
ASSERT_NULL (node->Left)
{
save = node->Right;
node_cb(map, node);
node = NULL;
}
else
{
save = node->Left;
node->Left = save->Right;
save->Right = node;
}
node = save;
}
}
free(map);
}
}
int
rb_tree_test(struct TMap* map, struct Node* root)
{
int lh, rh;
if (root == NULL)
return 1;
else
{
struct Node* ln = root->Left;
struct Node* rn = root->Right;
/* Consecutive red links */
if (TMapIsNodeRed(root))
{
if (AreNodesRed(ln,rn))
{
printf("Red violation");
return 0;
}
}
lh = rb_tree_test(map, ln);
rh = rb_tree_test(map, rn);
/* Invalid binary search tree */
if
((ln != NULL && map->compareNodeFunction(map, ln, root) >= 0)
|| (rn != NULL && map->compareNodeFunction(map, rn, root) <= 0))
{
puts("Binary tree violation");
return 0;
}
/* Black height mismatch */
if (lh != 0 && rh != 0 && lh != rh)
{
puts("Black violation");
return 0;
}
/* Only count black links */
if (lh != 0 && rh != 0)
return TMapIsNodeRed(root) ? lh : lh + 1;
else
return 0;
}
}
void* TMapFind(struct TMap* map, CByte* value)
{
void* result = NULL;
ASSERT_NOT_NULL (map)
{
struct Node node;
node.value = value;
struct Node* it = map->root;
int cmp = 0;
while (it)
{
if ((cmp = map->compareNodeFunction(map, it, &node)))
{
it = cmp < 0 ? it->Right : it->Left;
}
else
break;
}
result = it ? it->value : NULL;
}
return result;
}
#define CompareANullElement(nonNull,Null) ((!Null || !nonNull) ? (0) : nonNull==Null)
int TMapInsertNode(struct TMap* self, struct Node* node)
{
int result = 0;
if (self && node)
{
ASSERT_NULL (self->root)
{
self->root = node;
result = 1;
}
else
{
struct Node head = { NULL };
struct Node* g, * t;
struct Node* p, * q;
int dir = 0, last = 0;
// Set up our helpers
t = &head;
g = p = NULL;
q = t->Right = self->root;
while (1)
{
ASSERT_NULL (q)
{
// Insert node at the first null link.
p->Left = q = node;
}
else if (AreNodesRed(q->Left,q->Right))
{
q->color = 0;//red
q->Left->color = 1;// black
q->Right->color = 1;// black
}
if (AreNodesRed(q,p))
{
int dir2 = CompareANullElement(t->Right,g);
if (CompareANullElement(q,(last == 0 ? p->Left : p->Right)))
{
t->Right = TMapNodeRotateL(self,g,!last);
}
else
{
t->Left = TMapNodeRotateR(self,g,!last);
}
}
// Stop working if we inserted a node. This
// check also disallows duplicates in the tree
if (self->compareNodeFunction(self, q, node) == 0)
{
break;
}
last = dir;
dir = self->compareNodeFunction(self, q, node) < 0;
// Move the helpers down
if (g != NULL)
{
t = g;
}
g = p, p = q;
q = dir ==0 ? q->Left : q->Right;
}
// Update the root (it may be different)
self->root = head.Right;
}
// Make the root black for simplified logic
self->root->color = 1;
++self->TSize;
}
return 1;
}
int TMapInsert(struct TMap* map, CByte* value)
{
return TMapInsertNode(map, TMapInitializationCreateNode(value));
}
int TMapRemoveFrom(struct TMap* map, CByte* value, TMapNode_F node_cb)
{
ASSERT_NOT_NULL (map->root)
{
struct Node head = { 0 };
struct Node node;
node.value = value ;
struct Node* q, * p, * g;
struct Node* f = NULL;
int dir = 1;
q = &head;
g = p = NULL;
q->Right = map->root;
while ((dir == 0 ? q->Left : q->Right) != NULL)
{
int last = dir;
g = p, p = q;
q = dir == 0 ? q->Left : q->Right;
dir = map->compareNodeFunction(map, q, &node) < 0;
if (map->compareNodeFunction(map, q, &node) == 0)
{
f = q;
}
// Push the red node down with rotations and color flips
if (TMapIsNodeBlack(q) && TMapIsNodeBlack(dir == 0 ? q->Left : q->Right))
{
if (TMapIsNodeRed(!dir == 0 ? q->Left : q->Right))
{
p = last == 0 ? p->Left : p->Right = TMapNodeRotateL(map,q,dir);
}
else if (TMapIsNodeBlack(!dir == 0 ? q->Left : q->Right))
{
struct Node* s = !last == 0 ? p->Left : p->Right;
if (s)
{
if (TMapAreNodesBlack(!last == 0 ? s->Left : s->Right,last == 0 ? s->Left : s->Right))
{
// Color flip
p->color = 1;
s->color = 0;
q->color = 0;
}
else
{
int dir2 = g->Right == p;
if (TMapIsNodeRed(last == 0 ? s->Left : s->Right)) //check for red
{
dir2 == 0 ? s->Left : s->Right = TMapNodeRotateR(map,p,last);
}
else if (TMapIsNodeBlack((last != 0 ? s->Left : s->Right)))
{
dir2 == 0 ? g->Left: g->Right = TMapNodeRotateL(map,p,last);
}
// Ensure correct coloring
q->color = dir2 == 0 ? g->Left->color : g->Right->color = 0;
dir2==0 ? g->Left->Left->color : g->Right->Left->color = 1;
dir2 == 0 ? g->Left->Right->color : g->Right->Right->color = 1;
}
}
}
}
}
// Replace and remove the saved node
ASSERT_NOT_NULL (f)
{
CByte* tmp = f->value;
f->value = q->value;
q->value = tmp;
p->Right == q ? p->Right : p->Left = ((q->Left == NULL) ? q->Right: q->Left);
ASSERT_NOT_NULL (node_cb)
{
node_cb(map, q);
}
q = NULL;
}
// Update the root (it may be different)
map->root = head.Right;
// Make the root black for simplified logic
if (map->root != NULL)
{
map->root->color = 1;
}
--map->TSize;
}
return 1;
}
int TMapRemoveTree(struct TMap* map, CByte* value)
{
int result = 0;
ASSERT_NOT_NULL (map)
{
result = TMapRemoveFrom(map, value, TMapNodeDealloc);
}
return result;
}
size_t TMapGetSize(struct TMap* map)
{
size_t result = 0;
ASSERT_NOT_NULL(map)
{
result = map->TSize;
}
return result;
}
int my_cmp_cb(struct TMap* self, struct Node* node_a, struct Node* node_b)
{
BYTES* a = (BYTES*) node_a->value;
BYTES* b = (BYTES*) node_b->value;
return (a->value > b->value) - (a->value < b->value);
}
int main()
{
int t = true;
int d,c = 1;
(t ? d : c) = 2;
struct TMap* tree = TMapCreate(my_cmp_cb);
std::cout << sizeof(*tree) << std::endl;
ASSERT_NOT_NULL (tree)
{
BYTES* bytes = (BYTES*)calloc(1000,sizeof(BYTES));
std::stringstream ss;
// Use the tree here...
for (int i = 0; i < 1000; i++)
{
// Default insert, which allocates internal rb_nodes for you.
ss << i;
auto message = std::string("Hello " + ss.str());
unsigned char* val = new unsigned char[message.length() + 1];
strcpy((char*)val, message.c_str());
bytes[i].value = val;
bytes[i].index = i;
bytes[i].length = sizeof(message) / sizeof(unsigned char*);
TMapInsert(tree, &bytes[i]);
ss.str("");
ss.clear();
}
std::string str ="Hello 2";
BYTES b { (unsigned char*)str.c_str(), 2, 8 };
// To f
BYTES* f = (BYTES*)TMapFind(tree, &b);
if (f)
{
fprintf(stdout, "found BYTES(value = %s, index = %ull, length = %ull )\n", f->value,f->index,f->length);
}
else {
printf("not found\n");
}
TMapDealloc(tree, NULL);
}
}
[1]: https://github.com/mirek/rb_tree/blob/master/rb_tree.c

Alphabetically sorted links in doubly linked list

I've been having some trouble getting my program to insert given names along with their weights in a linked list which has a respective link for names and weights, which are both to be sorted in ascending / alphabetical order. The weight links work fine but I can't seem to identify what I'm getting wrong in my name linker. Any help would be greatly appreciated. The problem most likely lies in the insertName() private function.
#include <iostream>
#include <string>
using namespace std;
class DoublyLinkedList
{
public:
void insert(string name, double weight);
void printNameAsc();
void printWeightAsc();
private:
struct Node
{
string name;
double weight;
Node* nextName;
Node* nextWeight;
};
Node* nameHead = NULL;
Node* weightHead = NULL;
Node* newP = NULL;
void insertName();
void insertWeight();
};
void DoublyLinkedList::insert(string name, double weight)
{
// variable declaration
newP = new Node;
newP->name = name;
newP->weight = weight;
newP->nextName = NULL;
newP->nextWeight = NULL;
// empty first element check
if (nameHead == NULL && weightHead == NULL)
{
nameHead = newP;
weightHead = newP;
return;
}
// name and weight insertion
insertName();
insertWeight();
return;
}
void DoublyLinkedList::insertName()
{
Node* activeP = nameHead;
Node* prevP = NULL;
// traversing through name links
while (true)
{
if (activeP == NULL)
{
break;
}
if ((activeP->name).compare(newP->name))
{
break;
}
prevP = activeP;
activeP = activeP->nextName;
}
//insertion
newP->nextName = activeP;
if (activeP == nameHead)
{
nameHead = newP;
}
else
{
prevP->nextName = newP;
}
return;
}
void DoublyLinkedList::insertWeight()
{
Node* activeP = weightHead;
Node* prevP = NULL;
// traversing through weight links
while (true)
{
if (activeP == NULL)
{
break;
}
if (newP->weight < activeP->weight)
{
break;
}
prevP = activeP;
activeP = activeP->nextWeight;
}
//insertion
newP->nextWeight = activeP;
if (activeP == weightHead)
{
weightHead = newP;
}
else
{
prevP->nextWeight = newP;
}
return;
}
void DoublyLinkedList::printNameAsc()
{
Node* activeP = nameHead;
while (activeP != NULL)
{
cout << activeP->name << " " << activeP->weight << endl;
activeP = activeP->nextName;
}
return;
}
void DoublyLinkedList::printWeightAsc()
{
Node* activeP = weightHead;
while (activeP != NULL)
{
cout << activeP->name << " " << activeP->weight << endl;
activeP = activeP->nextWeight;
}
return;
}
int main()
{
DoublyLinkedList nameList;
nameList.insert("Michael", 275);
nameList.insert("Tom", 150);
nameList.insert("Abe", 200);
nameList.printNameAsc();
system("pause");
nameList.printWeightAsc();
system("pause");
return 0;
}
Pretty sure your problem is here:
if ((activeP->name).compare(newP->name) > 0)
{
break;
}
Looks like you're finding the insertion point with activeP. When activeP->name > newP->name, you want to stop searching.
if ((activeP->name).compare(newP->name))
Is invalid, this will evaluate true if activeP < newP (compare statement is -1) or activeP > newP (compare statement is 1), effectively only skipping people with the same names.
Remember, carried over from C, truth is defined as not falseness, which is defined as (!0)
Also, why not just pass a reference of newP to insertName() and insertWeight()? It's good practice to not leave (possibly dangling) pointers stored as member variables.

AVL tree(c++), program keeps on crashing

I am working on an exercise in processing an AVL tree. The debugger shows no errors. I ran the program and it is supposed to output an output text file. However the program crashes every time.
#include <stdio.h>
#include <assert.h>
#include <algorithm>
#include <vector>
using namespace std;
struct node
{
int key;
int height;
node *left, *right;
node(int k)
{
key = k;
height = 1;
left = right = 0;
}
};
void pre_order(node* root)
{
if(root == 0) return;
printf("%d", root->key);
printf(" ");
pre_order(root->left);
pre_order(root->right);
}
void in_order(node* root)
{
in_order(root->left);
printf("%d", root->key);
printf(" ");
in_order(root->right);
}
int height(node* r)
{
return r ? r->height : 0;
}
void update_height(node* root)
{
if(root == 0) return;
int hl = height(root->left), hr = height(root->right);
root->height = std::max(hl, hr) + 1;
}
node* right_rotate(node* ref_root)
{
assert(ref_root && ref_root->left);
node *a = ref_root, *b = ref_root->left;
a->left = b->right;
b->right = a;
update_height(a);
update_height(b);
return b;
}
node* left_rotate(node* ref_root)
{
assert(ref_root && ref_root->right);
node *c = ref_root, *d = ref_root->right;
c->right = d->left;
d->left = c;
update_height(c);
update_height(d);
return d;
}
node* maintain(node* ref_root)
{
if(ref_root == 0) return ref_root;
update_height(ref_root);
node* ret = ref_root;
if(height(ref_root->left) > height(ref_root->right) + 1)
{
node* p = ref_root->left;
if( height(p->left) < height(p->right) )
ref_root->left = left_rotate(p);
ret = right_rotate(ref_root);
}
else if(height(ref_root->right) > height(ref_root->left) + 1)
{
node* p = ref_root->right;
if(height(p->right) < height(p->left)){
ref_root->right = right_rotate(p);
}
ret = left_rotate(ref_root);
}
return ret;
}
node* insert_key(int key, node* ref_root)
{
if(ref_root == 0)
{
return ref_root = new node(key);
}
if(key < ref_root->key){
node* child = insert_key(key, ref_root->left);
ref_root->left = child;
}
else if(key > ref_root->key){
node* child = insert_key(key, ref_root->right);
ref_root->right = child;
}
else
assert(0);
return maintain(ref_root);
}
vector<node*> minimum(node* T) {
vector<node*> x;
node* y = T;
while (y->left != NULL) {
x.push_back(y->left);
}
return x;
}
node* delete_key(int key, node* ref_root)
{
if(key < ref_root->key){
node* child = delete_key(key, ref_root->left);
ref_root->left = child;
}
else if(key > ref_root->key){
node* child = delete_key(key, ref_root->right);
ref_root->right = child;
}
else
{
if(ref_root->left && ref_root->right)
{
vector <node*> y = minimum(ref_root->right);
node* successor = y.back();
node* sParent = y[y.size()-2];
ref_root->key = successor->key;
sParent->left = successor->right;
}
else
{
if(ref_root->left != NULL){
ref_root = ref_root->left;
}
else if(ref_root->right != NULL){
ref_root = ref_root->right;
}
}
}
return maintain(ref_root);
}
int main()
{
node *root = 0;
char op[10] = "";
int k;
while(true)
{
scanf("%s", op);
if(op[0] == 'E') break;
switch(op[0])
{
case 'A': scanf("%d", &k); root = insert_key(k, root); break; //Insert
case 'D': scanf("%d", &k); root = delete_key(k, root); break;//Delete
case 'P': pre_order(root); printf("\n"); break;//preorder
case 'I': in_order(root); printf("\n"); break;//inorder
default: assert(0);
}
}
return 0;
}
There is no check in the in_order function that root is not NULL.

Node does not name a type error

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(...).

C++ AVL Tree Deletion

So, I want to take input from a text file, then do some operations in an AVL tree. I could implement insertion, yet I can't build a solution for deletion in my mind. Can you help me? Here is the code.
#include<iostream>
#include<cstdio>
#include<sstream>
#include<algorithm>
#include <fstream>
#include <stdlib.h>
#include <array>
#include <ctime>
using namespace std;
struct node
{
int data;
int height;
struct node *leftchild;
struct node *rightchild;
}*root;
class avlTree
{
public:
int height(node *);
int difference(node *);
node *rrtraversal(node *);
node *lltraversal(node *);
node *lrtraversal(node *);
node *rltraversal(node *);
node* balance(node *);
node* insert(node *, int );
void display(node *, int);
node *del(node *, int);
avlTree()
{
root = NULL;
}
};
int avlTree::height(node *temp)
{
int h = 0;
if (temp != NULL)
{
int l_height = height (temp->leftchild);
int r_height = height (temp->rightchild);
int max_height = max (l_height, r_height);
h = max_height + 1;
}
return h;
}
int avlTree::difference(node *temp)
{
int l_height = height (temp->leftchild);
int r_height = height (temp->rightchild);
int b_factor= l_height - r_height;
return b_factor;
}
node *avlTree::rrtraversal(node *parent)
{
node *temp;
temp = parent->rightchild;
parent->rightchild = temp->leftchild;
temp->leftchild = parent;
return temp;
}
node *avlTree::lltraversal(node *parent)
{
node *temp;
temp = parent->leftchild;
parent->leftchild = temp->rightchild;
temp->rightchild = parent;
return temp;
}
node *avlTree::lrtraversal(node *parent)
{
node *temp;
temp = parent->leftchild;
parent->leftchild = rrtraversal (temp);
return lltraversal (parent);
}
node *avlTree::rltraversal(node *parent)
{
node *temp;
temp = parent->rightchild;
parent->rightchild = lltraversal (temp);
return rrtraversal (parent);
}
node *avlTree::balance(node *temp)
{
int bal_factor = difference (temp);
if (bal_factor > 1)
{
if (difference (temp->leftchild) > 0)
temp = lltraversal (temp);
else
temp = lrtraversal (temp);
}
else if (bal_factor < -1)
{
if (difference (temp->rightchild) > 0)
temp = rltraversal (temp);
else
temp = rrtraversal (temp);
}
return temp;
}
node *avlTree::insert(node *root, int value)
{
if (root == NULL)
{
root = new node;
root->data = value;
root->leftchild = NULL;
root->rightchild = NULL;
return root;
}
else if (value < root->data)
{
root->leftchild = insert(root->leftchild, value);
root = balance (root);
}
else if (value >= root->data)
{
root->rightchild = insert(root->rightchild, value);
root = balance (root);
}
return root;
}
void avlTree::display(node *ptr, int level)
{
int i;
if (ptr!=NULL)
{
display(ptr->rightchild, level + 1);
printf("\n");
for (i = 0; i < level && ptr != root; i++)
cout<<" ";
cout<<ptr->data;
display(ptr->leftchild, level + 1);
}
}
node *avlTree::del(node *root, int x)
{
node *d;
if ( x < root->data){
del(root->leftchild,x);
}
else if (x > root->data){
del(root->rightchild,x);
}
else if ((root->leftchild == NULL) && (root->rightchild == NULL))
{
d=root;
free(d);
root=NULL;
}
else if (root->leftchild == NULL)
{
d=root;
free(d);
root= root->rightchild;
}
else if (root->rightchild == NULL)
{
d=root;
root=root->leftchild;
free(d);
}
return root;
}
int main()
{
ifstream myFile("file.txt");
int a = 0;
std::array<string,512> arrayTest;
int index = 0;
string content;
avlTree avl;
while (myFile >> content){
arrayTest[index] = content;
index++;
}
clock_t startTime = clock();
for(a = 0; a < arrayTest.size();a++){
if(arrayTest[a] == "i"){
root = avl.insert(root, std::stoi(arrayTest[a+1]));
}
}
avl.display(root,1);
clock_t endTime = clock();
clock_t clockTicksTaken = endTime - startTime;
double timeInSeconds = clockTicksTaken / (double) CLOCKS_PER_SEC;
cout << "\n\n" << timeInSeconds << " secs\n";
}
In file, the content is like this. i 1 i 2 i 3 i 4 i 5 d 3
If program sees i, it will do an insert operation. Likewise, if it sees d, it will do a delete operation.
Did you try free() function?
free(node);