Breadth First Traversal With Binary Search Tree C++ - c++

Maybe fast/simple Question. I have a a Binary Tree Implemented already, Then I was hoping to convert binary search tree into an array or at least print it out as if in an array. Where I am having trouble with is how to get the NULL/flags in there '\0'.
for example lets say I have a tree like:
10
/ \
6 12
/ \ \
1 8 15
\
4
And I want it to print how its supposed to print. Like:
[10,6,12,1,8,\0,15,\0,4,\0,\0,\0,\0,\0,\0]
^Something Like this^ I don't know if I counted the NULL correctly.
Or Another Option on how i want to go about showing Visually my Tree is how to get the spacing correctly outputted like with the '/' and '\' pointing to the keys from the parents:
10
/ \
6 12
/ \ \
1 8 15
\
4
Here is something that I tried elaborating on code wise but im stuck:
void BreadthFirstTravseral(struct node* root)
{
queue<node*> q;
if (!root) {
return;
}
for (q.push(root); !q.empty(); q.pop()) {
const node * const temp_node = q.front();
cout<<temp_node->data << " ";
if (temp_node->left) {
q.push(temp_node->left);
}
if (temp_node->right) {
q.push(temp_node->right);
}
}
}
Any Kind of Help or Link and or advice and or example code would be very much appreciated.

It will be very hard to get the spacing correctly as a key may have multiple digits and this should affect the spacing for all levels above the given node.
As for how to add NULL - simply add else clauses for your ifs where you print a NULL:
if (root) {
q.push(root);
cout << root->data << " ";
} else {
cout << "NULL ";
}
while (!q.empty()) {
const node * const temp_node = q.front();
q.pop();
if (temp_node->left) {
q.push(temp_node->left);
cout << temp_node->left->data << " ";
} else {
cout << "NULL ";
}
if (temp_node->right) {
q.push(temp_node->right);
cout << temp_node->right->data << " ";
} else {
cout << "NULL ";
}
}

void TreeBreadthFirst(Node* treeRoot)
{
Queue *queue = new Queue();
if (treeRoot == NULL) return;
queue->insert(treeRoot);
while (!queue->IsEmpty())
{
Node * traverse = queue->dequeue();
cout<< traverse->data << “ “ ;
if (traverse->left != NULL)
queue->insert( traverse->left);
if (traverse->right != NULL)
queue->insert(traverse->right);
}
delete queue;
}

I've made a program in c. This code will display somewhat like a tree.
struct node{
int val;
struct node *l,*r;
};
typedef struct node node;
int findDepth(node *t){
if(!t) return 0;
int l,r;
l=findDepth(t->l);
r=findDepth(t->r);
return l>r?l+1:r+1;
}
void disp(node *t){
if(!t)
return;
int l,r,i=0;
node *a[100],*p;
int front=0,rear=-1,d[100],dep,cur,h;
a[++rear]=t;
d[rear]=0;
cur=-1;
h=findDepth(t);
printf("\nDepth : %d \n",h-1);
while(rear>=front){
dep = d[front];
p=a[front++];
if(dep>cur){
cur=dep;
printf("\n");
for(i=0;i<h-cur;i++) printf("\t");
}
if(p){
printf("%d\t\t",p->val);
a[++rear]=p->l;
d[rear]=dep+1;
a[++rear]=p->r;
d[rear]=dep+1;
}
else printf ("-\t\t");
}
}

void BreadthFirstTravseral(struct node* root)
{
queue<node*> q;
if (!root) {
return;
}
for (q.push(root); !q.empty(); q.pop()) {
const node * const temp_node = q.front();
if( temp_node->special_blank ){
cout << "\\0 " ;
continue;//don't keep pushing blanks
}else{
cout<<temp_node->data << " ";
}
if (temp_node->left) {
q.push(temp_node->left);
}else{
//push special node blank
}
if (temp_node->right) {
q.push(temp_node->right);
}else{
//push special node blank
}
}
}

How about this:
std::vector<node*> list;
list.push_back(root);
int i = 0;
while (i != list.size()) {
if (list[i] != null) {
node* n = list[i];
list.push_back(n->left);
list.push_back(n->right);
}
i++;
}
Not tested but I think it should work.

Related

Why is it that, when I try to shift all of the strings into my custom made Queue template and try to print, it only prints the last in the queue?

Truth be told, this is an assignment that I'm trying to complete. The basic thing that we have to do is create a Stack and Queue without STL and then create Stack and Queue with STL. I pretty much finished up creating my custom Stack, and it works perfectly. However, with Queue, whenever I try to shift strings into it and print it out, the console will only print out the string that was the last to be shifted. On top of that, whenever I try to unshift the last thing entered into the Queue with the code that I have, I end up getting a read access violation, that of which I am completely stumped on resolving.
If you don't mind, can you look through my code and help me understand what I did that is causing this error and the last entry in my Queue to be the only one printed out? Thanks in advance.
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
struct Node {
//create a node struct
string data;
Node *next;
};
class Stack {
public:
Stack();
~Stack();
void push(string a);
string pop();
string toString();
bool isEmpty();
private:
Node * top;
};
class Queue {
public:
Queue();
~Queue();
void shift(string a);
string unshift();
string toString();
bool isEmpty();
private:
Node * top;
Node * bottom;
int count;
};
Stack::Stack() {
//initializes stack to be empty
top = NULL;
}
Queue::Queue() {
//initializes stack to be empty
top = NULL;
}
Stack::~Stack() {
//deconstructor to delete all of the dynamic variable
if (top == NULL) {
cout << "Nothing to clean up" << endl;
}
else {
cout << "Should be deleting..." << endl;
}
}
Queue::~Queue() {
//deconstructor to delete all of the dynamic variable
if (bottom == NULL) {
cout << "Nothing to clean up" << endl;
}
else {
cout << "Should be deleting..." << endl;
}
}
void Stack::push(string a) {
//Need a new node to store d in
Node *temp = new Node;
temp->data = a;
temp->next = top;//point the new node's next to the old top of the stack
top = temp;//point top to the new top of the stack
}
void Queue::shift(string a) {
//Need a new node to store d in
Node *temp = new Node;
temp->data = a;
temp->next = NULL;//point the new node's next to the old top of the stack
if (isEmpty()) {
top = temp;
}
else {
top->next = temp;
count++;
}
top = temp;//point top to the new top of the stack
}
string Stack::pop() {
if (!isEmpty()) {
string value = top->data;
Node *oldtop = top;
top = oldtop->next;
delete oldtop;
return value;
}
else {
cout << "You can't pop from an empty stack!" << endl;
exit(1);
}
}
string Queue::unshift() {
if (isEmpty()) {
cout << "You can't unshift an empty Queue!" << endl;
exit(1);
}
else{
Node *oldbot = top;
if (top == bottom) {
top = NULL;
bottom = NULL;
}
else {
string value = top->data;
}
delete oldbot;
count--;
}
}
string Stack::toString() {
string result = "top ->";
if (isEmpty()) {
result = result + "NULL";
return result;
}
else {
Node *current = top;
while (current != NULL) {
result = result + current->data + "->";
current = current->next;
}
result = result + "(END)";
return result;
}
}
string Queue::toString() {
string result = "top ->";
if (isEmpty()) {
result = result + "NULL";
return result;
}
else {
Node *current =top;
while (current != NULL) {
result = result + current->data + "->";
current = current->next;
}
result = result + "(END)";
return result;
}
}
bool Stack::isEmpty() {
return(top == NULL);
}
bool Queue::isEmpty() {
return(top == NULL);
}
int main()
{
Stack *s = new Stack();
cout << "Output when empty: " << endl << s->toString() << endl;
s->push("Cheeseburger");
s->push("Pizza");
s->push("Large coffee");
s->pop();
cout << "Output when not empty: " << endl << s->toString() << endl;
delete s;
cin.get();
Queue *b = new Queue();
cout << "Output when empty: " << endl << b->toString() << endl;
b->shift("Cheeseburger");
b->shift("Pizza");
b->shift("Large coffee");
cout << "Output when not empty: " << endl << b->toString() << endl;
b->unshift();
delete b;
cin.get();
}
You have to comment below statement in Queue::shift method -
top = temp;

Segmentation fault in UNIX but not Windows

I'm trying to get my DFS code working in UNIX, but whenever I run it it gives me a segmentation fault, yet it works fine in Windows. The code is supposed to take in a string and sort it to reach some predefined goal state by moving around a single letter at a time. I don't have much experience in UNIX so I would really appreciate some insight into this issue. Thank you!
struct node
{
node* parent;
string key;
int cost;
int heuristicCost;
node()
{
parent = nullptr;
key = "key";
cost = 0;
heuristicCost = 0;
}
};
void BFS(string sortString)
{
// Create Queue
list<node*> queue;
list<string> explored;
// Add the initial case to the Queue
node *n = new node;
n->key = sortString;
queue.push_back(n);
int steps = 1;
while (!queue.empty())
{
// Print out the current node to be checked and the operation that was performed on it
for (int i = 0; i < (int)queue.front()->key.length(); i++)
{
if (queue.front()->key[i] == 'X')
{
if (steps == 1)
{
cout << queue.front()->key << endl;
steps++;
}
else
{
cout << "move " << i << " " << queue.front()->key << endl;
steps++;
}
}
}
// Check if the goal state is reached
if (GoalTest(queue.front()->key))
{
cout << "Final Result for BFS:" << endl;
node* currentNode = queue.front();
list<node*> path;
while (currentNode->parent != nullptr) {
path.push_front(currentNode);
currentNode = currentNode->parent;
}
int i = 1;
while((int)path.size() >= 1)
{
cout << "Step " << i << ": " << path.front()->key << endl;
i++;
path.pop_front();
}
return;
}
else
{
// If goal state is not reached, add new nodes to the frontier
explored.push_back(queue.front()->key);
for (int i = 0; i < (int)queue.front()->key.length(); i++)
{
// Do a move action on the next node to be enqueued, if node is already in explored list, skip it
string key = Move(i, queue.front()->key);
bool found = (find(explored.begin(), explored.end(), key) != explored.end());
if (found)
{
continue;
}
else
{
node *newNode = new node;
newNode->key = key;
newNode->parent = queue.front();
queue.push_back(newNode);
}
}
// Remove the first node of the queue
queue.pop_front();
bool found = (find(explored.begin(), explored.end(), queue.front()->key) != explored.end());
while (found)
{
queue.pop_front();
found = (find(explored.begin(), explored.end(), queue.front()->key) != explored.end());
}
}
}
// If loop exits normally, search failed
cout << "Failure!" << endl;
return;
}

Output of c++ program not coming as expected

I have made a C++ program for a binary tree. But the terminal is not asking the statement for inputting the direction for where the elements are to be placed.
Also when I replace the statement from " node *temp = new node " to "node *temp=NULL" the program stops working .
#include <iostream>
#include <cstring>
using namespace std;
class node {
int data;
node * left;
node * right;
public:
node * level_order(node * first);
node * create_bt(node * first);
void display(node * first);
};
//node *first=NULL;
node * node::create_bt(node * first) {
node * temp = new node;
int ele;
//char dir;
cout << "\n Enter data ";
cin >> ele;
temp->data = ele;
temp->left = NULL;
temp->right = NULL;
if (first == NULL) {
temp = first;
return first;
} else {
char dir[20];
cout << "\n Enter the direction ";
cin >> dir;
node * cur = first;
int j = 0;
while (dir[j] != '\0') {
if (dir[j] == 'l') {
cur = cur->left;
}
if (dir[j] == 'r') {
cur = cur->right;
}
j++;
}
cur = temp;
return first;
}
}
void node::display(node * first) {
if (first == NULL)
return;
cout << "\n " << first->data;
display(first->left);
display(first->right);
}
int main() {
int n;
node s;
node * first = NULL;
cout << "\n No of elements ";
cin >> n;
for (int i = 0; i < n; i++) {
first = s.create_bt(first);
}
s.display(first);
return 0;
}
first=s.create_bt(first); does not changes state, from NULL to 'l' or 'r'. You have to change that.
node*node::create_bt(node *first)
{
node *temp=new node;
int ele;
//char dir;
cout<<"\n Enter data ";
cin>>ele;
temp->data=ele;
temp->left=NULL;
temp->right=NULL;
char dir[20];
cout<<"\n Enter the direction ";
cin>>dir;
if(first==NULL)
{
temp=first;
return first;
}
else
{
node*cur=first;
int j=0;
while(dir[j]!='\0')
{
if(dir[j]=='l')
{
cur=cur->left;
}
if(dir[j]=='r')
{
cur=cur->right;
}
j++;
}
cur=temp;
return first;
}
}
I believe you re looking something like this. This is a basic binary tree, i had to make a basic one in order to understand how it works and how it chooses left and right. I make a class inside a class, in order to have access to my data members (node class, int data, *left , *right) and have them at the same time protected, all-in-one. As you can see "newnode" just creates a node and NULL s the pointers. Thats it. "Find" searches and finds a node with a current key, and returns it when exits. All the rest, i guess, you can understand them, as they are prety much the same with your code. The only thing you have to do is to define, when you want to direct the node you want. REMINDER: You have to find a way to utilize it, so the leafs will not end far-left or far-right.("Enter the direction"). I hope i helped you understand.
#include <iostream>
#include <conio.h>
using namespace std;
class mybTree {
class node {
public:
int data;
node * left;
node *right;
};
node *root;
node *newnode(int num){
node *newnode1;
newnode1 = new (nothrow) node;
newnode1->data = num;
newnode1->left = NULL;
newnode1->right = NULL;
return newnode1;
}
public:
node *find (int key) {
node *current;
current = root;
while (current->data !=key){
if (key<current->data){
current = current->left;
} else {
current = current->right;
}
if (current == NULL){
return NULL;
}
}
return NULL;
}
void display (node *ptr);
void display_tree();
bool insert(int num);
void post_order_delete(node *ptr);
mybTree();
~mybTree();
};
int main(){
char ch = ' ';
int a;
mybTree mybTree1;
while (ch !='0'){
cout << "0->Exit"<<endl<< "1-> add"<<endl<< "2-> find" <<endl<<"3-> Show me the tree\n";
ch = getch();
switch (ch) {
case '0':
break;
case '1':
cout << "number";
cin >> a;
if (!mybTree1.insert(a)){
cout << "Not enough memory" << endl;
}
break;
case '2' :
cout << "Number:" ;
cin >> a;
if (mybTree1.find(a)!=NULL) {
cout << "Found" << endl;
} else {
cout << "Not existed" << endl;
}
break;
case '3':
mybTree1.display_tree();
cout<<endl;
break;
default:
cout << "Wrong Message";
break;
}
}
return 0;
}
void mybTree::display(node *ptr) {
if (ptr == NULL){
return;
}
display(ptr->left);
cout << ptr->data<<endl;
display(ptr->right);
}
void mybTree::display_tree() {
//Displays the Tree
display(root);
}
bool mybTree::insert(int num) {
//It inserts a node. Desides left or right.
node *next,*current,*ptr;
int isleft;
next = current = root;
ptr = newnode(num);
if (ptr == NULL) {
return false;
}
if (root == NULL) {
root = ptr;
return true;
}
while (1){
if (num < current->data){
next = current->left;
isleft = 1;
} else {
next = current->right;
isleft = 0;
}
if (next == NULL){
if (isleft){
current->left = ptr;
} else {
current->right = ptr;
}
return true;
}
current=next;
}
return false;
}
void mybTree::post_order_delete(node *ptr) {
//deletes the node. Usefull for destructor
if (ptr == NULL){
return;
}
post_order_delete(ptr->left);
post_order_delete(ptr->right);
cout << ptr->data;
delete ptr;
}
mybTree::mybTree() {
//Constructor
root = NULL;
}
mybTree::~mybTree() {
//Destructor
post_order_delete(root);
root = NULL;
}

c++ Stuck making an binary tree implementation with an array and lists

I am working on writing a list of children binary tree implementation. In my code I have an array of lists. Each list contains a node followed by its children on the tree. I finished writing the code and everything compiled, but I keep getting a segmentation fault error and I cannot figure out why. I have been attempting to debug and figure out where my code messes up. I know that there is an issue with the FIRST function. It causes a segmentation fault. Also, when I try to print just one of the lists of the array, it prints everything. I have been stuck on this for a very long time now and would like some help. Can anyone offer suggestions as to why the FIRST and PRINT functions are not working? Maybe there is a large error that I just cannot see.
My code is as follows:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <array>
#include <string.h>
using namespace std;
struct node
{
char element;
struct node *next;
}*start;
class list
{
public:
void ADD(char n);
node* CREATE(char n);
void BEGIN(char n);
char FIRST();
char END();
char NEXT(char n);
char PREVIOUS(char n);
int LOCATE(char n);
void EMPTY();
void PRINT();
list()
{
start = NULL;
}
};
char PARENT(const char n, list tree[], int length)
{
int i=0;
list l;
for (i; i<length; i++)
{
l = tree[i];
if (n != l.FIRST())
{
if (l.LOCATE(n)>0)
return l.FIRST();
}
}
}
char LEFTMOST_CHILD(char n, list tree[], int length)
{
int i;
list l;
for (i=0; i<length; i++)
{
l = tree[i];
if (l.FIRST() == n)
return l.NEXT(n);
}
}
char RIGHT_SIBLING(char n, list tree[], int length)
{
int i;
list l;
for (i=0; i<length; i++)
{
l = tree[i];
if(n != l.FIRST())
{
if (l.LOCATE(n) > 0)
{
return l.NEXT(n);
}
}
}
}
char ROOT(list tree[]) //assumes array is in order, root is first item
{
list l;
l = tree[0];
cout << "Assigned tree to l" << endl;
return l.FIRST();
}
void MAKENULL(list tree[], int length)
{
int i;
list l;
for (i=0; i<length; i++)
{
l = tree[i];
l.EMPTY();
}
}
void list::PRINT()
{
struct node *temp;
if (start == NULL)
{
cout << "The list is empty" << endl;
return;
}
temp = start;
cout << "The list is: " << endl;
while (temp != NULL)
{
cout << temp->element << "->" ;
temp = temp->next;
}
cout << "NULL" << endl << endl;
}
void list::EMPTY()
{
struct node *s, *n;
s = start;
while (s != NULL)
{
n = s->next;
free(s);
s = n;
}
start = NULL;
}
int list::LOCATE(char n)
{
int pos = 0;
bool flag = false;
struct node *s;
s = start;
while (s != NULL)
{
pos++;
if (s->element == n)
{
flag == true;
return pos;
}
s = s->next;
}
if (!flag)
return -1;
}
void list::ADD(char n)
{
struct node *temp, *s;
temp = CREATE(n);
s = start;
while (s->next != NULL)
s = s->next;
temp->next = NULL;
s->next = temp;
}
node *list::CREATE(char n)
{
struct node *temp;
temp = new(struct node);
temp->element = n;
temp->next = NULL;
return temp;
}
void list::BEGIN(char n)
{
struct node *temp, *p;
temp = CREATE(n);
if (start == NULL)
{
start = temp;
start->next = NULL;
}
}
char list::FIRST()
{
char n;
struct node *s;
s = start;
cout << "s = start" << endl;
n = s->element;
cout << "n" << endl;
return n;
}
char list::END()
{
struct node *s;
s = start;
int n;
while (s != NULL)
{
n = s->element;
s = s->next;
}
return n;
}
char list::NEXT(char n)
{
char next;
struct node *s;
s = start;
while (s != NULL)
{
if (s->element == n)
break;
s = s->next;
}
s = s->next;
next = s->element;
return next;
}
char list::PREVIOUS(char n)
{
char previous;
struct node *s;
s = start;
while (s != NULL)
{
previous = s->element;
s = s->next;
if (s->element == n)
break;
}
return previous;
}
main()
{
list a,b,c,d,e,f,g,h,i,j,k,l,m,n;
a.BEGIN('A');
b.BEGIN('B');
c.BEGIN('C');
d.BEGIN('D');
e.BEGIN('E');
f.BEGIN('F');
g.BEGIN('G');
h.BEGIN('H');
i.BEGIN('I');
j.BEGIN('J');
k.BEGIN('K');
l.BEGIN('L');
m.BEGIN('M');
n.BEGIN('N');
a.ADD('B');
a.ADD('C');
b.ADD('D');
b.ADD('E');
e.ADD('I');
i.ADD('M');
i.ADD('N');
c.ADD('F');
c.ADD('G');
c.ADD('H');
g.ADD('J');
g.ADD('K');
h.ADD('L');
a.PRINT();
list tree[] = {a,b,c,d,e,f,g,h,i,j,k,l,m,n};
int length = sizeof(tree)/sizeof(char);
char root = ROOT(tree);
cout << "Found root" << endl;
char parent = PARENT('G', tree, length);
cout << "Found Parent" << endl;
char leftChild = LEFTMOST_CHILD('C', tree, length);
cout << "found left child" << endl;
char rightSibling = RIGHT_SIBLING('D', tree, length);
cout << "found right sibling" << endl;
cout << "The root of the tree is: ";
cout << root << endl;
cout << "The parent of G is: ";
cout << parent << endl;
cout << "The leftmost child of C is" ;
cout << leftChild << endl;
cout << "The right sibling of D is: " ;
cout << rightSibling << endl;
}
Any help will be very appreciated. Thanks you!
The fundamental problem is that you have written a lot of code before testing any of it. When you write code, start with something small and simple that works perfectly, add complexity a little at a time, test at every step, and never add to code that doesn't work.
The specific problem (or at least one fatal problem) is here:
struct node
{
char element;
struct node *next;
}*start;
class list
{
public:
//...
list()
{
start = NULL;
}
};
The variable start is a global variable. The class list has no member variables, but uses the global variable. It sets start to NULL every time a list is constructed, and every list messes with the same pointer. The function FIRST dereferences a pointer without checking whether the pointer is NULL, and when it is, you get Undefined Behavior.
It's not entirely clear what you intended, but you seem to misunderstand how variables work in C++.

Level Order Traversal: Deleting a Subtree

#include <iostream>
using namespace std;
struct node {
int item;
node* l;
node* r;
node (int x) {
item = x;
l = 0;
r = 0;
}
node(int x, node* l, node* r) {
item = x;
this->l = l;
this->r = r;
}
};
typedef node* link;
class QUEUE {
private:
link* q;
int N;
int head;
int tail;
public:
QUEUE(int maxN) {
q = new link[maxN + 1];
N = maxN + 1;
head = N;
tail = 0;
}
int empty() const {
return head % N == tail;
}
void put(link item) {
q[tail++] = item;
tail = tail % N;
}
link get() {
head = head % N;
return q[head++];
}
};
link head = 0; // Initial head of the tree
link find(int x) {
if (head == 0) {
cout << "\nEmpty Tree\n";
return 0;
}
link temp = head;
// To find the node with the value x and return its link
QUEUE q(100);
q.put(temp);
while (!q.empty()) {
temp = q.get();
if (temp->item == x) {
return temp;
}
if (temp->l != 0) q.put(temp->l);
if (temp->r != 0) q.put(temp->r);
}
return 0;
}
void print(link temp) {
QUEUE q(100);
q.put(temp);
while (!q.empty()) {
temp = q.get();
cout << temp->item << ", ";
if (temp->l != 0) q.put(temp->l);
if (temp->r != 0) q.put(temp->r);
}
}
void deleteAll(link h) {
// This deletes the entire binary tree
QUEUE q(100);
q.put(h);
while (!q.empty()) {
h = q.get();
if (h->l != 0) q.put(h->l);
if (h->r != 0) q.put(h->r);
delete h;
}
}
int main() {
link temp = 0;
char c;
int n1, n2;
cout << "\n\nPlease enter the input instructions (X to exit program) : \n\n";
do {
cin >> c;
switch (c) {
case 'C': cin >> n1;
if (head == 0) {
head = new node(n1);
cout << "\nRoot node with item " << n1 << " has been created\n\n";
} else {
cout << "\nError: Tree is not empty\n\n";
}
break;
case 'L': cin >> n1 >> n2;
temp = find(n1);
if (temp != 0) {
if (temp->l == 0) {
temp->l = new node(n2);
cout << "\nNode with item " << n2 << " has been added\n\n";
}
else {
cout << "\nError: The specified node already has a left child\n\n";
}
}
else {
cout << "\nError: The specified node doesn't exist\n\n";
}
break;
case 'R': cin >> n1 >> n2;
temp = find(n1);
if (temp != 0) {
if (temp->r == 0) {
temp->r = new node(n2);
cout << "\nNode with item " << n2 << " has been added\n\n";
}
else {
cout << "\nError: The specified node already has a right child\n\n";
}
}
else {
cout << "\nError: The specified node doesn't exist\n\n";
}
break;
case 'P': cin >> n1;
temp = find(n1);
if (head != 0) {
cout << "\nLevel-order traversal of the entire tree: ";
print(temp);
}
else {
cout << "\nError: No elements to print\n\n";
}
break;
case 'D': cin >> n1;
temp = find(n1);
deleteAll(temp);
temp = 0;
break;
case 'X': cout << "\nExiting Program\n\n";
break;
default: cout << "\nInvalid input entered. Try again.\n\n";
}
} while (c != 'X');
system("pause");
return 0;
}
Sample Input:
C 9
L 9 8
R 9 6
L 8 3
R 8 5
R 6 2
L 3 4
L 4 10
L 5 1
R 5 11
L 1 12
R 1 7
It all works fine until I delete a subtree and print when it prints garbage value before crashing. Please help me figure out the bug because I've been trying in vain for hours now.
It all works fine until I delete a subtree and print when it prints garbage value before crashing. Please help me figure out the bug because I've been trying in vain for hours now.
Try the recursive function:
void Delete(link h)
{
if(h)
{
if(h->l) Delete(h->l);
if(h->r) Delete(h->r);
delete(h);
}
}
When you delete a node, you call deleteAll(temp) which deletes temp, but it doesn't remove the pointer value from the l or r of temp's parent node.
This leaves you with a invalid pointer, causing garbage printing and crashing.
Unfortunately, the way your find works currently, you don't know what the current temp node's parent is when you get around to checking its value.
One way to fix it is to have a different type of find (called something like remove) that looks in l and r at each iteration for the value and sets l or r to NULL before returning the pointer. You might have to have a special case for when the value is found in the root.
Edit (sample code added):
I am assuming you are not using recursion for some reason, so my code uses your existing queue based code. I only changed enough to get it working.
findAndUnlink find the node with the value given and "unlinks" it from the tree. It returns the node found, giving you a completely separate tree. Note: it is up to the caller to free up the returned tree, otherwise you will leak memory.
This is a drop in replacement for find in your existing code, as your existing code then calls deleteAll on the returned node.
link findAndUnlink(int x) {
if (head == 0) {
cout << "\nEmpty Tree\n";
return 0;
}
link temp = head;
if (temp->item == x) {
// remove whole tree
head = NULL;
return temp;
}
// To find the node with the value x and remove it from the tree and return its link
QUEUE q(100);
q.put(temp);
while (!q.empty()) {
temp = q.get();
if (temp->l != NULL) {
if (temp->l->item == x) {
link returnLink = temp->l;
temp->l = NULL;
return returnLink;
}
q.put(temp->l);
}
if (temp->r != NULL) {
if (temp->r->item == x) {
link returnLink = temp->r;
temp->r = NULL;
return returnLink;
}
q.put(temp->r);
}
}
return 0;
}