Binary Search Tree - make remove function in virtual machine with Linux - c++

This is my own BST(binary search tree functions)
When I compile, it occurs segmentation error(core dumped)
which part is wrong?
I think there is no logic error
Please see my codes and give me advices
void Tree::remove(int data){
TreeNode *cursor=this->rootnode;
while(1){
if(cursor == NULL){
cout<<endl;
cout<<data<<" remove failed"<<endl;
return;
}
TreeNode *tNode;
int value=cursor->getData();
if(value==data){
if(cursor->getRight() != NULL && cursor->getLeft() != NULL){
tNode = findMaxNode(cursor->getLeft());
int num=tNode->getData();
cursor->setData(num);
cursor=cursor->getLeft();
remove(num);
}
else
{
tNode = (cursor->getLeft() == NULL) ? cursor->getRight() : cursor->getLeft();
free(cursor);
cout<<data<<" remove success!"<<endl;
return;
}
}
else if(data>value){
cursor=cursor->getRight();
remove(data);
}
else if(data<value){
cursor=cursor->getLeft();
remove(data);
}
}
}

You should to use (more) the recursivity to solve your problem. I hope that this code will help you.
void Tree::remove(int data)
{
if(this->rootnode == NULL)
{
cout<<data<<" remove failed"<<endl;
return;
}
remove(this->rootnode, data);
}
void Tree::remove(TreeNode* &cursor, int data)
{
if (cursor != NULL)
{
if (data == cursor->getData())
{
remove(cursor->getLeft(), data);
remove(cursor->getRight(), data);
delete cursor;
cursor = NULL;
}
}
}

Related

How to implement complete binary in c++?

I want to try make insertion of complete binary tree using recursion . I make a piece of code and I cannot catch problem why value not inserted. I make height function and count nodes function with help of these function and recursive call I want to insert new node in Complete binary tree. In main get root by using get root function then send to insert function
#include<iostream>
#include<math.h>
using namespace std;
struct node{
int data;
node *left,*right;
};
class cbt{
node *root;
public:
cbt()
{
root=NULL;
}
node* get_node()
{
return root;
}
node* newNode(int key)
{
node* temp1 = new node;
temp1->data = key;
temp1->left = temp1->right = NULL;
return temp1;
}
void CBT_inseration(node* temp,int data)
{
node *ptr;
ptr=newNode(data);
if(root==NULL)
{
root=ptr;
return;
}
else
{
height = f_height(temp->left);
int excepted_node = pow(2,height)-1;
int left_tree_node_count = countNumNodes(temp->left);
int right_tree_node_count = countNumNodes(temp->right);
if(left_tree_node_count==right_tree_node_count)
{
CBT_inseration(temp->left,data);
}
else if(excepted_node != left_tree_node_count)
{
if(temp->left == NULL)
{
temp->left = ptr;
return;
}else
{
CBT_inseration(temp->left,data);
}
}
else if(temp->right == NULL)
{
temp->right=ptr;
return;
}
else if(excepted_node != left_tree_node_count)
{
if(temp->left == NULL)
{
temp->left=ptr;
return;
}
else
{
CBT_inseration(temp->right,data);
}
}
}
}
void print(node *root) {
if (root == NULL)
return;
print(root->left);
cout << root->data << " ";
print(root->right);
}
};
int main()
{
cbt obj;
node *r=NULL;
obj.CBT_inseration(obj.get_node(),4);
obj.CBT_inseration(obj.get_node(),3);
obj.CBT_inseration(obj.get_node(),5);
obj.CBT_inseration(obj.get_node(),8);
obj.print(obj.get_node());
return 0;
}
You would need to go through a debugger to see what is wrong with your code. I will tell you how I would do this:
First, you need a function to check if the tree is full. We will reuse your functions to do this:
bool isTreeFull(node* head) {
return head != NULL && countNumNodes(head) == (1 << find_height(head)) - 1;
}
Then for inserting I have to check if the number of nodes on each side are the same. This tells me that I am allowed to move one level deeper on the left side. If the number of nodes aren't the same, then I only move on to insert on the right subtree if the left subtree is full:
void CBT_inseration(int data) {
root = insert(root, data);
}
node* insert(node* head, int data) {
if (head == NULL) {
head = newNode(data);
} else {
int leftCount = countNumNodes(head->left);
int rightCount = countNumNodes(head->right);
if (leftCount == rightCount) {
head->left = insert(head->left, data);
} else {
if (isTreeFull(head->left)) {
head->right = insert(head->right, data);
} else {
head->left = insert(head->left, data);
}
}
}
return head;
}
Then you would call it like:
cbt obj;
obj.CBT_inseration(4);
obj.CBT_inseration(3);
obj.CBT_inseration(5);
obj.CBT_inseration(6);
obj.CBT_inseration(8);
obj.print(obj.get_node()); // 6 3 8 4 5

Error when Deleting Node from BST

This genuinely has me stumped. I have a binary search tree of citys that is ordered by the city name. A city also contains the population and GPS coordinates. I want to be able to remove nodes from the tree by City name or city coordinates. I have the delete by name working fine but the GPS coordinates does not work.
When I remove a node by GPS I get a stack-overflow when I try to print the binary tree. Below is some of my code. I cannot understand how it will work fine if I delete by name but not if I delete by coordinates as I am using the same delete method.
The exact error I get is "Unhandled exception at 0x013214D6 in EXE: 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x00152FFC)." This occurs in my print function after I delete by coordinates but not if I delete by name.
bool BinaryTree::DeleteByName(string city)
{
if (GetRoot() != NULL)
{
return (DeleteByName(GetRoot(), city));
}
return false;
}
TreeNode* BinaryTree::DeleteByName(TreeNode *node, string city)
{
if (node == NULL)
{
return node;
}
else if (city < node->Data.name)
{
node->Left = DeleteByName(node->Left, city);
}
else if (city > node->Data.name)
{
node->Right = DeleteByName(node->Right, city);
}
else
{
if (node->Left == NULL && node->Right == NULL)
{
delete node;
node = NULL;
}
else if (node->Left == NULL)
{
TreeNode* temp = node;
node = node->Right;
delete temp;
}
else if (node->Right == NULL)
{
TreeNode* temp = node;
node = node->Left;
delete temp;
}
else
{
cout << "Else";
TreeNode* temp = MinPtr(node->Right);
node->Data = temp->Data;
node->Right = DeleteByName(node->Right, temp->Data.name);
}
}
return node;
}
bool BinaryTree::DeleteByCoord(pair<double, double> coords)
{
if (GetRoot() == NULL)
{
return false;
}
else
{
return DeleteByCoord(GetRoot(), coords);
}
}
bool BinaryTree::DeleteByCoord(TreeNode* node, pair<double, double> coords)
{
bool result;
if (node == NULL)
{
return false;
}
else
{
if (node->Data.coordinates.first == coords.first && node->Data.coordinates.second == coords.second)
{
return (DeleteByName(node, node->Data.name));
}
result = DeleteByCoord(node->Left, coords);
if (result == true)
{
return result;
}
return DeleteByCoord(node->Right, coords);
}
}
void BinaryTree::Insert(City city)
{
TreeNode* temp = new TreeNode(city);
if (GetRoot() == NULL)
{
root = temp;
}
else
{
Insert(temp, GetRoot());
}
}
void BinaryTree::Insert(TreeNode* toAdd, TreeNode* addHere)
{
if (toAdd->Data < addHere->Data)
{
if (addHere->Left != NULL)
{
Insert(toAdd, addHere->Left);
}
else
{
addHere->Left = toAdd;
}
}
else if (toAdd->Data > addHere->Data)
{
if (addHere->Right != NULL)
{
Insert(toAdd, addHere->Right);
}
else
{
addHere->Right = toAdd;
}
}
}
void BinaryTree::InOrderTraversal(TreeNode* node)
{
if (node != NULL)
{
InOrderTraversal(node->Left);
cout << node->Data << endl;
InOrderTraversal(node->Right);
}
}
void BinaryTree::InOrderTraversal()
{
InOrderTraversal(GetRoot());
}
TreeNode* BinaryTree::GetRoot()
{
return root;
}
TreeNode* BinaryTree::MinPtr(TreeNode* node)
{
while (node->Left != NULL)
{
node = node->Left;
}
return node;
}
When you delete the node you also need to update parent pointer that points to deleted node. Pay attention here:
when you call DeleteByName directly it searches required node and returns NULL pointer which automatically set to parent node pointer:
else if (city < node->Data.name)
{
node->Left = DeleteByName(node->Left, city);
}
else if (city > node->Data.name)
{
node->Right = DeleteByName(node->Right, city);
}
but when you call DeleteByName from coordinates method you do not reset parent's Left/Right pointers:
if (node->Data.coordinates.first == coords.first && node->Data.coordinates.second == coords.second)
{
return (DeleteByName(node, node->Data.name));
}
in its turn as DeleteByName already receives required node, it does not perform recursive call and does not reset parent's pointers either:
else
{
if (node->Left == NULL && node->Right == NULL)
{
delete node;
node = NULL;
}
//... same here
}
NOTE: There are many more problems in your code. Some that strike the eye:
DeleteByName returns pointer, but DeleteByCoord returns bool, you use pointer as a boolean type in DeleteByCoord
Avoid to compare doubles directly, the comparison result can be wrong. See the question and explanation for the details.

Binary search tree two similar functions producing garbage

I've got this call
productTree.displayNode(productTree.newsearchTree(search, productTree.Root()));
Calling these functions
void Tree::displayNode(Node* node) {
if (node != NULL) {
cout << node->productdata << endl;
}
}
Node* Tree::newsearchTree(string search, Node* node) {
if (node != NULL) {
newsearchTree(search, node->left);
if (search == node->productdata.getName()) {
return node;
}
newsearchTree(search, node->right);
}
}
Node* Root() { return root; };
Which produces a garbage output when trying to display the returned node.
And yet, I can traverse my tree and display it easily this way:
This call:
productTree.Inorder(productTree.Root());
Functions:
void Tree::Inorder(Node* node) {
if (node != NULL) {
Inorder(node->left);
displayNode(node);
Inorder(node->right);
}
}
And where I am confused is how are they different?
Edit: Thank you for your help, I modified the code as below and it works fine now:
Node* Tree::newsearchTree(string search, Node* node) {
if (node != NULL) {
newsearchTree(search, node->left);
if (search == node->productdata.getName()) {
return node;
}
newsearchTree(search, node->right);
}
return NULL;
}
void Tree::displayNode(Node* node) {
if (node != NULL) {
cout << node->productdata << endl;
}
else if (node == NULL) {
cout << "Product not found" << endl;
}
}
Yep, that's still broken. This finally fixed it I believe:
Node* Tree::newsearchTree(string search, Node* node) {
if (node != NULL) {
if (search == node->key) {
return node;
}
if (search < node->key) {
return newsearchTree(search, node->left);
}
else {
return newsearchTree(search, node->right);
}
}
else return NULL;
}
Let me add comments inline to make it clear what your Tree::newsearchTree does.
Node* Tree::newsearchTree(string search, Node* node) {
if (node != NULL) {
newsearchTree(search, node->left); // burn CPU but leaves no side effect
if (search == node->productdata.getName()) {
return node; // return node only if the root node equals 'search'
}
newsearchTree(search, node->right); // burn CPU without side effect
}
// In majority of the cases (root node != 'search'): return nothing.
}
Because typically newsearchTree() returns nothing, when you call productTree.displayNode(productTree.newsearchTree(...)) you basically print garbage.

Removing a Node in a BST

I am having trouble getting my remove300 and removeNode300 function working correctly when I remove the root of the tree. (In my case 8). Everything works right(compiling wise), but when I call me inView function, which displays the numbers in the binary tree in ascending order, it takes that 8 out and just puts the highest number in 8's place.
For example:
I insert these numbers in this order, 8,4,12,2,6,10,14,20 and call me remove function to remove 8. I get this output 2,4,5,20,10,12,14. I want it to be 2,4,6,10,12,14,20.
If I can get some help on this on why this process isn't working please let me know. Also let me know if I have to add anything to this post inorder to help you.
Struct definition:
typedef float Element300;
struct TreeNode300;
typedef TreeNode300 * TreePtr300;
struct TreeNode300
{
Element300 element;
TreePtr300 left;
TreePtr300 right;
};
Remove Function:
void BST300::remove300(const Element300 element, TreePtr300 & root)
{
if(root == NULL)
{
cerr << "Error: Remove Failed!" << endl;
}
else if(element == root->element )
{
removeNode300(root);
}
else if(element < root->element)
{
remove300(element, root->left);
}
else
{
remove300(element, root->right);
}
return;
}
Remove Node function:
void BST300::removeNode300(TreePtr300 & root)
{
TreePtr300 tempPointer = NULL;
if(root->left == NULL && root->right == NULL)
{
delete root;
root = NULL;
}
else if(root->right == NULL)
{
tempPointer = root;
root = root->left;
tempPointer->left = NULL;
delete tempPointer;
}
else if(root->left == NULL)
{
tempPointer = root;
root = root->right;
tempPointer->right = NULL;
delete tempPointer;
}
else
{
findMaxNode300(root->right, tempPointer);
root->element = tempPointer->element;
delete tempPointer;
}
tempPointer = NULL;
return;
}
find Maximum value function:
void BST300::findMaxNode300(TreePtr300 & root, TreePtr300 & tempPointer)
{
if(root->right == NULL)
{
tempPointer = root;
root = root->left;
tempPointer->left = NULL;
}
else
{
findMaxNode300(root->right, tempPointer);
}
return;
}

not able to create Binary search tree in c++

My InsertInTree function is not working properly, and I am not able to figure out my problem. Please suggest changes I can make (but I don't want to use recursion).
It takes values from the structure and the function GetNewNode returns the node with left and right pointer as NULL:
public:
void InsertInTree(int piData)
{
Node*newNode = NULL;
newNode=GetNewNode(piData);
if(root==NULL)
{
root=newNode;
return;
}
Node*temp = root;
while(temp!=NULL)
{
if(newNode->data<=temp->data)
{
temp=temp->left;
}
else
{
temp=temp->right;
}
}
temp=newNode;
return;
}
bool SearchNum(int piSearch)
{
if(root==NULL)
{
return false;
}
Node*temp=root;
while(temp!=NULL)
{
if(temp->data==piSearch)
{
return true;
}
else if(piSearch<=temp->data)
{
temp=temp->left;
}
else
{
temp=temp->right;
}
}
if(temp==NULL)
{
return false;
}
else
{
return true;
}
}
Assuming root is global. you should use one more node i.e. *pre (previousnode).
*pre=NULL;
while(temp!=NULL){
if(newnode->data<=temp->data){
pre=temp;
temp=temp->left;
}else{
pre=temp;
temp=temp->right;
}
}
if(newnode->data<=pre->data)
pre->left=newnode;
else
pre->right=newnode;
this will solve the problem..
The following should fix your issue:
void InsertInTree(int piData)
{
Node* newNode = GetNewNode(piData);
Node** temp = &root;
while (*temp != NULL)
{
if (newNode->data <= (*temp)->data)
{
temp = &(*temp)->left;
}
else
{
temp = &(*temp)->right;
}
}
*temp = newNode;
}