Binary Search Tree Traversals - binary-tree

I have just started learning Binary Trees and went ahead and tried to implement my own in C. I am kinda lost as to why only InOrder Traversal is displaying correctly while the other two are wrong. I really can't figure this out. I even directly tried inserting nodes, and the result is the same.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct Node
{
int val;
struct Node *left;
struct Node *right;
};
//Allocate Memory for New Node
struct Node* getNewNode(int val)
{
struct Node * ptr = (struct Node*)malloc(sizeof(struct Node));
ptr->val = val;
ptr->left = NULL;
ptr->right = NULL;
return ptr;
}
//Insert Node in Binary Search Tree
struct Node* insertNode(struct Node* root,int val)
{
if(root == NULL)
{
root = getNewNode(val);
}
else if(val <= root->val)
{
root->left = insertNode(root->left,val);
}
else
{
root->right = insertNode(root->right,val);
}
return root;
}
void printInorder(struct Node* root)
{
if(root == NULL) return;
printInorder(root->left);
printf("%d ",root->val);
printInorder(root->right);
}
void printPostOrder(struct Node* root)
{
if(root == NULL) return;
printInorder(root->left);
printInorder(root->right);
printf("%d ",root->val);
}
void printPreOrder(struct Node*root)
{
if(root == NULL) return;
printf("%d ",root->val);
printInorder(root->left);
printInorder(root->right);
}
bool search(struct Node* root,int val)
{
if(root == NULL)
{
return false;
}
else if(val == root->val)
{
return true;
}
else if(val < root->val)
{
return search(root->left,val);
}
else
{
return search(root->right,val);
}
}
int main(void)
{
struct Node * root = NULL; //Tree is Empty
root = insertNode(root,15);
root = insertNode(root,10);
root = insertNode(root,8);
root = insertNode(root,12);
root = insertNode(root,20);
root = insertNode(root,17);
root = insertNode(root,25);
printf("Printing In-Order: \n");
printInorder(root);
printf("\nPrinting Post-Order: \n");
printPostOrder(root);
printf("\nPrinting Pre-Order: \n");
printPreOrder(root);
// if(search(root,11))
// {
// printf("\nValue Found\n");
// }
// else
// {
// printf("\nValue Not Found\n");
// }
return 0;
}
Please help me understand if I am doing this wrong or my understanding of traversals is faulty.
The output is as follows:
output terminal

You have copy-paste errors in printPostOrder and printPreOrder - they both call printInorder where they should be calling themselves.

Related

Inaccuracy in output of deletion function in binary search tree

I am making a binary search tree code, in that 'am facing an issue in the deletion function. After executing the function, the code is showing inorder display incorrectly. Basically, it is incorrect, and I'am not able to understand where the problem is.
In the delete function, I have used a search function that will find the node which the user has to delete. And I have used inorder successor method for deletion so the minimum function will find the successor. All other functions like insertion, minimum, and inorder are working fine.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *left;
struct node *right;
} node;
struct node *insert(struct node *tnode, int data)
{
if (tnode == NULL)
{
struct node *ptr;
ptr = (struct node *)malloc(sizeof(struct node));
ptr->data = data;
ptr->left = NULL;
ptr->right = NULL;
return ptr;
}
if (data > (tnode->data))
{
tnode->right = insert(tnode->right, data);
return tnode;
}
if (data < (tnode->data))
{
tnode->left = insert(tnode->left, data);
return tnode;
}
}
void in_order(struct node *tnode)
{
if (tnode == NULL)
return;
else
{
in_order(tnode->left);
printf("%d\t", tnode->data);
in_order(tnode->right);
}
}
struct node *search(struct node *tnode, int data)
{
if (tnode == NULL)
{
return NULL;
}
else
{
if (data == tnode->data)
{
return tnode;
}
else
{
if (data > tnode->data)
{
search(tnode->right, data);
}
else
{
search(tnode->left, data);
}
}
}
}
struct node *minimum(struct node *tnode)
{
if (tnode == NULL)
{
printf("No node present\n");
return NULL;
}
else
{
if (tnode->left == NULL)
return tnode;
else
minimum(tnode->left);
}
}
struct node *deletenode(struct node *tnode, int data)
{
struct node *s;
s = search(tnode, data);
if (s == NULL)
{
printf("Value not found\n");
return NULL;
}
else
{
if (s->left == NULL && s->right == NULL) // No child case
{
free(s);
return NULL;
}
else
{
if (s->left == NULL && s->right != NULL) // single child case(right child)
{
struct node *temp = s->right;
free(s);
return temp;
}
else if (s->right == NULL && s->left != NULL) // single child case(left child)
{
struct node *temp = s->left;
free(s);
return temp;
}
else
{
struct node *temp;
temp = minimum(s->right);
s->data = temp->data;
s->right = deletenode(s->right, temp->data);
}
}
}
return s;
}
int main()
{
struct node *root = NULL, *del;
int n, i, data, key;
printf("Enter how many nodes you have to enter in a tree\n");
scanf("%d", &n);
for (i = 0; i < n; i++)
{
printf("Enter data\n");
scanf("%d", &data);
root = insert(root, data);
}
printf("\nIN-Order display\n");
in_order(root);
int d;
printf("\nEnter data to be delete\n");
scanf("%d", &d);
del=deletenode(root, d);
printf("\nIN-Order display\n");
in_order(root);
return 0;
}
There are several places missing return (in minimum, search and deletenode). You can easily find them if you compile with -Wall -Wextra compiler options.
It is not clear, what do you want to return from deletenode. I assume that it is a tree with deleted element. Then either search should return a parent node (so it is possible to change pointers to freed node), or deletenode should move to parent node.
Also, use in_order(del) instead of in_order(root) because root can be changed while deleting.

Find the Error or memory leak

I was writing LinkedList Program in C++
Here is the Code. Find the Error and Memory Leak or anything else.
I want to write a perfect code.
#ifndef LEARN_REVERSELINKLIST_H
#define LEARN_REVERSELINKLIST_H
#include <string>
#include <utility>
#include <iostream>
#include <boost/assert.hpp>
class ReverseLinkList {
private:
struct Node {
std::string string;
Node *Previous{};
Node *Next{};
};
Node *head;
Node *tail;
int count;
public:
ReverseLinkList();
~ReverseLinkList();
void insert(std::string string);
void insertAt(std::string string, int position);
void iterator() const;
void reverseIterator() const;
void remove(const std::string &string);
void removeAt(int position);
int size() const;
Node *getHead() const;
Node *getTail() const;
};
#endif //LEARN_REVERSELINKLIST_H
and Here is the CC File
#include "ReverseLinkList.h"
ReverseLinkList::~ReverseLinkList() {
if (count != 0) {
Node *temp = head;
while (temp != tail->Next) {
delete temp->Previous;
temp = temp->Next;
}
tail = nullptr;
head = nullptr;
}
}
ReverseLinkList::ReverseLinkList()
: head(nullptr), tail(nullptr), count(0) {
}
void ReverseLinkList::iterator() const {
BOOST_ASSERT_MSG(count != 0, "List is empty");
Node *temp;
temp = head;
while (temp != tail->Next) {
std::cout << temp->string << std::endl;
temp = temp->Next;
}
}
void ReverseLinkList::reverseIterator() const {
BOOST_ASSERT_MSG(count != 0, "List is empty");
Node *temp;
temp = tail;
while (temp != head->Previous) {
std::cout << temp->string << std::endl;
temp = temp->Previous;
}
}
void ReverseLinkList::insert(std::string string) {
auto *newNode = new Node;
newNode->string = std::move(string);
count++;
if (head == nullptr && tail == nullptr) {
newNode->Previous = nullptr;
newNode->Next = nullptr;
head = newNode;
tail = newNode;
} else {
tail->Next = newNode;
newNode->Next = nullptr;
newNode->Previous = tail;
tail = newNode;
}
}
int ReverseLinkList::size() const {
return count;
}
void ReverseLinkList::remove(const std::string &string) {
BOOST_ASSERT_MSG(count != 0, "List is empty");
if (count == 1) {
if (head->string == string) {
delete head;
head = nullptr;
tail = nullptr;
}
count--;
return;
}
if (head->string == string) {
Node *temp;
temp = head->Next;
delete head;
head = temp;
head->Previous = nullptr;
count--;
return;
}
if (tail->string == string) {
Node *temp;
temp = tail->Previous;
delete tail;
tail = temp;
temp->Next = nullptr;
count--;
return;
}
Node *temp;
temp = head;
bool verbose = true;
while (temp != tail->Next) {
if (temp->string == string) {
verbose = false;
break;
}
temp = temp->Next;
}
if (verbose) {
std::cerr << "Node not present" << std::endl;
return;
}
Node *previous, *next;
previous = temp->Previous;
next = temp->Next;
delete temp;
previous->Next = next;
next->Previous = previous;
count--;
}
void ReverseLinkList::insertAt(std::string string, int position) {
if (position > count)
return;
if (position == 0) {
if (head == nullptr) {
insert(string);
return;
}
auto *newNode = new Node;
newNode->string = string;
newNode->Previous = nullptr;
head->Previous = newNode;
newNode->Next = head;
head = newNode;
count++;
return;
}
if (position == count - 1) {
insert(string);
return;
}
Node *temp;
temp = head;
while (position != 0) {
temp = temp->Next;
position--;
}
Node *next;
next = temp->Next;
auto *newNode = new Node;
newNode->string = string;
temp->Next = newNode;
newNode->Previous = temp;
newNode->Next = next;
next->Previous = newNode;
count++;
}
ReverseLinkList::Node *ReverseLinkList::getHead() const {
return head;
}
ReverseLinkList::Node *ReverseLinkList::getTail() const {
return tail;
}
void ReverseLinkList::removeAt(int position) {
BOOST_ASSERT_MSG(count != 0, "List is empty");
if (position > count)
return;
Node *temp;
if (count == 1) {
delete head;
head = nullptr;
tail = nullptr;
count--;
return;
}
if (position == 0) {
temp = head->Next;
delete head;
head = temp;
head->Previous = nullptr;
count--;
return;
}
if (position == count) {
temp = tail->Previous;
delete tail;
tail = temp;
tail->Next = nullptr;
count--;
return;
}
temp = head;
while (position != 0) {
temp = temp->Next;
position--;
}
Node *previous;
Node *next;
previous = temp->Previous;
next = temp->Next;
delete temp;
previous->Next = next;
next->Previous = previous;
count--;
}
I would like to have some suggestion how can I write better code and Implement it. If you have some functions you would like to add please do post.
My next move is to make this code using templates

Doubly Linked List insert function

I am having problem with this code.Can someone help me to fix it ?
Problem is in insert function especially with malloc(allocating).I don't understand why I cannot malloc.It is not printing the debug text.
#include<stdlib.h>
#include<stdio.h>
#define TRUE 1
#define FALSE 0
struct Node{
int data;
struct Node* next;
struct Node* prev;
};
struct ListRecord
{
struct Node *head;
struct Node *tail;
int length;
};
typedef struct ListRecord *DoubleList;
DoubleList createList()
{
return NULL;
}
DoubleList MakeEmptyList(DoubleList l)
{
l = (struct ListRecord*)malloc(sizeof(struct ListRecord));
if(l==NULL)
{
printf("Memory allocation failed!");
}
else
{
l->head->next=NULL;
l->head->prev=NULL;
l->tail=l->head;
l->length=0;
}
}
DoubleList InsertListAtPosition(DoubleList l,int pos,int val)
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
printf("debug");
if(newNode==NULL)
{
printf("debug");
newNode->data=val;
newNode->next=NULL;
newNode->prev=NULL;
if(pos > l->length+1)
{
pos=l->length+1;
}
else if(pos==l->length+1)
{
struct Node *iterator=l->head;
while(iterator->next != NULL)
{
iterator=iterator->next;
}
iterator->next=newNode;
newNode->prev=iterator;
newNode->next=NULL;
}
else
{
struct Node* iterator=l->head;
int i;
for(i=0;i<pos;i++)
iterator=iterator->next;
newNode->next=iterator->next;
newNode->prev=iterator;
iterator->next->prev=newNode;
iterator->next=newNode;
}
l->length++;
}
else
{
printf("Memory allocation failed!");
}
}
int DeleteListAtPosition(DoubleList l,int pos)
{
int value;
if(l==NULL)
{
printf("List is empty");
return 0;
}
else
{
if(pos==1)
{
struct Node* iterator=l->head;
value=iterator->data;
free(iterator);
return value;
}
else
{
struct Node* iterator=l->head;
int i;
for(i=1;i<pos;i++)
iterator=iterator->next;
if(iterator->next==NULL)
{
value=iterator->data;
free(iterator);
return value;
}
else
{
iterator->prev->next=iterator->next;
iterator->next->prev=iterator->prev;
free(iterator);
}
}
}
}
void printList(DoubleList l) {
struct Node* temp = l->head;
printf("Forward: ");
while(temp != NULL) {
printf("%d ",temp->data);
temp = temp->next;
}
printf("\n");
}
int main(){
DoubleList myList;
int exit,pos,value;
char command;
myList=createList();
exit=FALSE;
while(!exit)
{
fflush(stdin);
printf("\nMenu:\n m)akeEmpty\n i)nsert\n e)xit\n");
scanf("%c", &command);
fflush(stdin);
switch(command)
{
case 'm':
myList = MakeEmptyList(myList);
break;
case 'i':
printf("Enter position to be added: ");
scanf("%d",&pos);
printf("Enter value to be added: ");
scanf("%d",&value);
InsertListAtPosition(myList,pos,value);
//printList(myList);
break;
case 'e':
exit = TRUE;
break;
default:
printf("command not recognized\n");
break;
}
}
printf("\n\n");
system("PAUSE");
return 0;
}
Here is the working code,
#include<stdlib.h>
#include<stdio.h>
#include <bits/stdc++.h>
#define TRUE 1
#define FALSE 0
using namespace std;
struct Node{
int data;
struct Node* next;
struct Node* prev;
};
struct ListRecord
{
struct Node *head;
struct Node *tail;
int length;
};
typedef struct ListRecord *DoubleList;
DoubleList createList()
{
return NULL;
}
DoubleList MakeEmptyList()
{
DoubleList l;
l = (struct ListRecord*)malloc(sizeof(struct ListRecord));
if(l==NULL)
{
printf("Memory allocation failed!");
}
else
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->next = NULL;
newNode->prev = NULL;
l->head = newNode;
l->tail=l->head;
l->length=0;
}
return l;
}
DoubleList InsertListAtPosition(DoubleList l,int pos,int val)
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
if(newNode != NULL)
{
newNode->data=val;
newNode->next=NULL;
newNode->prev=NULL;
if(pos > l->length)
{
pos=l->length+1;
}
else if(pos==l->length)
{
struct Node *iterator=l->head;
while(iterator->next != NULL)
{
iterator=iterator->next;
}
iterator->next=newNode;
newNode->prev=iterator;
newNode->next=NULL;
}
else
{
struct Node* iterator=l->head;
int i;
for(i=0;i<pos;i++)
iterator=iterator->next;
newNode->next=iterator->next;
newNode->prev=iterator;
iterator->next->prev=newNode;
iterator->next=newNode;
}
l->length++;
}
else
{
printf("Memory allocation failed!");
}
}
int DeleteListAtPosition(DoubleList l,int pos)
{
int value;
if(l==NULL)
{
printf("List is empty");
return 0;
}
else
{
if(pos==1)
{
struct Node* iterator=l->head;
value=iterator->data;
free(iterator);
return value;
}
else
{
struct Node* iterator=l->head;
int i;
for(i=1;i<pos;i++)
iterator=iterator->next;
if(iterator->next==NULL)
{
value=iterator->data;
free(iterator);
return value;
}
else
{
iterator->prev->next=iterator->next;
iterator->next->prev=iterator->prev;
free(iterator);
}
}
}
}
void printList(DoubleList l) {
struct Node* temp = l->head;
printf("Forward: ");
while(temp != NULL) {
printf("%d ",temp->data);
temp = temp->next;
}
printf("\n");
}
int main(){
DoubleList myList;
int exit,pos,value;
char command;
exit=FALSE;
while(!exit)
{
fflush(stdin);
printf("\nMenu:\n m)akeEmpty\n i)nsert\n e)xit\n");
scanf("%c", &command);
fflush(stdin);
switch(command)
{
case 'm':
myList = MakeEmptyList();
break;
case 'i':
printf("Enter position to be added: ");
scanf("%d",&pos);
printf("Enter value to be added: ");
scanf("%d",&value);
if(myList == NULL) {
myList = MakeEmptyList();
}
InsertListAtPosition(myList,pos,value);
//printList(myList);
break;
case 'e':
exit = TRUE;
break;
default:
printf("command not recognized\n");
break;
}
}
printf("\n\n");
system("PAUSE");
return 0;
}
So you were making the following mistakes,
Your MakeEmptyList method is returning nothing, it should return l.
Inside you insert you were checking with length + 1, instead of only length, so it was causing pointer related errors.

Insertion in BST

I was doing a problem on insertion. This is the right answer.
/*
Node is defined as
typedef struct node
{
int data;
node * left;
node * right;
}node;
*/
node * insert(node * root, int value)
{
if(root == NULL)
{
node *temp = new node();
temp->left = NULL;
temp->right = NULL;
temp->data = value;
root = temp;
return root;
}
if(value > root->data)
{
root->right = insert(root->right, value);
}
else
root->left = insert(root->left, value);
return root;
}
The only difference with the solution I made is that in the if/else statements I did not assign anything. This is my code.
Node is defined as
typedef struct node
{
int data;
node * left;
node * right;
}node;
*/
node * insert(node * root, int value)
{
if(root == NULL)
{
node *temp = new node();
temp->left = NULL;
temp->right = NULL;
temp->data = value;
root = temp;
return root;
}
if(value > root->data)
{
insert(root->right, value);
}
else
insert(root->left, value);
return root;
}
I am not sure I understand why this is necessary because basically calling this function recursively will find a right place for the node with the data value.
Then, I create node with right data and just insert it there.
I will leave a link to the problem. https://www.hackerrank.com/challenges/binary-search-tree-insertion
Thanks for help!

Trying to insert an Avl tree

I am trying to make an insertion method for an Avl tree but the structure and order of my nodes turns out to be incorrect. I am having trouble finding where i am going wrong.
Here are my methods
Any sort of help would be appreciated
template
void AvL<T>::insert(string val, T k)
{
if (head == NULL) {
head = new AvLNode<T>(val, k);
} else {
put(head, val, k);
}
}
template <class T>
void AvL<T>::put(AvLNode<T>* root,string val,T key1) {
if (root->key > key1) {
if (root->left != NULL) {
put(root->left, val, key1);
Balance(root, key1);
} else {
root->left = new AvLNode<T>(val, key1);
root->bf = nodeHeight(root->left) - nodeHeight(root->right);
root->left->parent = root;
}
} else {
if (root->right != NULL) {
put(root->right, val, key1);
Balance(root, key1);
} else {
root->right = new AvLNode<T>(val, key1);
root->bf = nodeHeight(root->left) - nodeHeight(root->right);
root->right->parent = root;
}
}
}
template<class T>
void AvL<T>::Balance(AvLNode<T>* root, T key1)
{ root->bf = nodeHeight(root->left) - nodeHeight(root->right);
if (root->bf < -1 && key1 > root->right->key) {
cout << "here1 ";
LeftRotate(root);
} else if (root->bf > 1 && key1 < root->left->key) {
cout << "here2 ";
RightRotate(root);
} else if (root->bf < -1 && key1 < root->right->key) {
RightRotate(root->right);
cout << "here3 ";
LeftRotate(root);
} else if (root->bf > 1 && key1 > root->left->key) {
LeftRotate(root->left);
cout << "here4 ";
RightRotate(root);
}
}
template<class T>
void AvL<T>::RightRotate(AvLNode<T>* node)
{
AvLNode<T>* node1 = node->left;
node->left = node1->right;
node1->right = node;
node->bf = nodeHeight(node->left) - nodeHeight(node->right);
node1->bf = nodeHeight(node1->left) - nodeHeight(node1->right);
node = node1;
}
template<class T>
void AvL<T>::LeftRotate(AvLNode<T>* node)
{
AvLNode<T>* node1 = node->right;
node->right = node1->left;
node1->left = node;
node->bf = nodeHeight(node->left) - nodeHeight(node->right);
node1->bf = nodeHeight(node1->left) - nodeHeight(node1->right);
node = node1;
}
template<class T>
int AvL<T>::nodeHeight( AvLNode<T> *n)
{
int lheight=0;
int rheight=0;
int h = 0;
if (n == NULL)
{
return -1;
} else {
lheight = nodeHeight(n->left);
rheight = nodeHeight(n->right);
h = 1+max(lheight,rheight);
return h;
}
}
My .h file
template <class T>
struct AvLNode
{
string value;
T key;
AvLNode *parent; // pointer to parent node
AvLNode *left; // pointer to left child
AvLNode *right; // pointer to right child
int bf; // Balance factor of node
AvLNode(string Val, T k)
{
this->value = Val;
this->key = k;
this->parent = NULL;
this->left = NULL;
this->right = NULL;
bf = 0;
}
};
template <class T>
class AvL
{
AvLNode<T> *head;
public:
// Constructor
AvL();
// Destructor
~AvL();
// Insertion Function
void insert(string val, T k); // inserts the given key value pair into the tree
void Balance(AvLNode<T>* node, T key1);
void delete_node(T k); // deletes the node for the given key
void RightRotate(AvLNode<T>* node);
void LeftRotate(AvLNode<T>* node);
void put(AvLNode<T>* root,string val,T key1);
int nodeHeight(AvLNode<T> *n); // returns height of the subtree from given node
};
Your balance function is wrong. Since you've already inserted your new node into the tree, you don't need to worry about the key any more in Balance() - so the prototype should look like this:
template<class T>
void AvL<T>::Balance(AvLNode<T>* root);
The way you're doing it now seems to be attempting to balance based on the key you just inserted - which isn't necessary! You can balance the tree just based on the balance factors of nodes - here's how.
template<class T>
void AvL<T>::Balance(AvLNode<T>* root) {
if (root->bf > 1) {
if (root->left->bf == -1) LeftRotate(root->left);
RightRotate(root);
} else if (root->bf < -1) {
if (root->right->bf == 1) RightRotate(root->right);
LeftRotate(root);
}
}
You can read more about it here - but you seem to have the idea almost down. The only thing you need to change conceptually is the idea that you're balancing based on the key you just inserted. You're not - you're balancing based on the shape of the tree, which you can get from just the balance factors of each subtree.

Resources