I am cuurently learning pointer arithmetics in C
as an exercise I would like to program a binary tree
so far i got the structure itself
typedef struct bintree
{ struct bintree *left;
struct bintree *right;
int value;
} bintree ;
the constructon of the tree
bintree *new_bintree (int value)
{ bintree *node = malloc(sizeof(bintree));
knoten -> left = NULL;
knoten -> right = NULL;
knoten -> value = value;
return (node);
}
the add node function
int bintree_add(bintree *tree, int value)
{ if (value == tree->value)
{return(-1);}
if ((value <= tree->value)&&(tree->left!=NULL)) /*Left node check and insert*/
{ return(bintree_add(tree->left, value));}
if ((value <= tree->value)&&(tree->left==NULL))
{bintree *knoten = malloc(sizeof(bintree));
knoten -> left = NULL;
knoten -> right = NULL;
knoten -> value = value;
tree -> left = node;
return(0);
}
if ((value >= tree->value)&&(tree->right!=NULL)) /*right node check and insert*/
{ return (bintree_add(tree->right, value));}
if ((value >=tree->value)&&(tree->right == NULL))
{bintree *knoten = malloc(sizeof(bintree));
knoten -> right = NULL;
knoten -> left = NULL;
knoten -> value = value;
tree -> right = node;
return (0);
}
}
and the clear function
void delete_bintree(bintree *tree)
{
if (tree->left != NULL)
{delete_bintree (tree->left);}
if (tree->right != NULL)
{delete_bintree (tree->right);}
free(tree);
}
now i would like to implement the DepthFirstSearch and the BreathFirstSearch
This is my so far code for the DFS
bool bintree_dsearch(bintree *tree, int value)
{
if (value == tree->value)
{return true;}
if (tree->value == NULL)
{return false;}
if (tree->left != NULL)
{return bintree_dsearch(tree->left, value);}
else return bintree_dsearch(tree->right, value);
}
any help is appreciated :)
thanks in advance
ok fixed it and now it is running fine
here's the code
bool bintree_dsearch(bintree *tree, int value)
{
if (value == tree->value)
{return true;}
if (tree->value == NULL)
{return false;}
if (tree->left != NULL)
{return bintree_dsearch(tree->left, value);}
if (tree->right != NULL)
{return bintree_dsearch(tree->right, value);}
}
Related
I am trying to create a function that deletes a node from a binary search tree my problem is whenever I delete a root node that has two children it will work but if I insert a node again there is an error in allocating memory(malloc) for the newly added node. I have tried using a debugger it will stuck in malloc and it doesn't tell me why.
Here is my function in deleting a node from the bst
bool delete_node(node * n, int data)
{
if(n == NULL)
return false;
if (n->data == data)
{
if(n->left == NULL && n->right == NULL)
{
free(n);
n->empty = true;
return true;
}
else if(n->left != NULL && n->right == NULL)
{
node * temp = n;
n = n->left;
free(temp);
temp->empty = true;
return true;
}
else if(n->left == NULL && n->right != NULL)
{
node * temp = n;
n = n->right;
free(temp);
temp->empty = true;
return true;
}
else
{
nodelist * inorder_seq = create_nodelist();
get_inorder_seq(inorder_seq, n);
node * ps = get_predecessor(inorder_seq, n);
if(ps == NULL)
ps = get_successor(inorder_seq, n);
int temp_data = n->data;
n->data = ps->data;
free(inorder_seq->list);
free(inorder_seq);
if(temp_data > n->data)
return delete_node(n->left, ps->data);
else
return delete_node(n->right, ps->data);
}
}
else if(n->data < data)
return delete_node(n->right, data);
else if(n->data > data)
return delete_node(n->left, data);
}
Here is my function in inserting a new node
void insert_node(node * root, int data)
{
node * newnode = create_node(data);
recur_insert_node(root, newnode);
}
Here is the function for the recursion of inserting a new node
void recur_insert_node(node * n, node * newnode)
{
if(n->data > newnode->data)
{
if(n->left == NULL || n->left->empty)
{
n->left = newnode;
n->left->empty = false;
}
else
{
recur_insert_node(n->left, newnode);
}
}
else if(n->data < newnode->data || n->right->empty)
{
if(n->right == NULL)
{
n->right = newnode;
n->right->empty = false;
}
else
{
recur_insert_node(n->right, newnode);
}
}
}
here is my node struct
typedef struct _node
{
int data;
struct _node * left;
struct _node * right;
bool empty;
}node;
I simply want to delete a node from the BST and this gives me an error that new is undefined.
The ADT is like this:
typedef struct BSTNode *BSTree;
struct BSTNode {
int value;
BSTree left;
BSTree right;
};
BSTree Delete(BSTree t, int item) {
if (item < t->value) {
t->left = Delete(t->left, item);
} else if (item > t->value) {
t->right = Delete(t->right, item);
} else {
// deleting item
if (t->left == NULL && t->right == NULL) {
BSTree new = NULL;
} else if (t->left == NULL) {
BSTree new = t->right;
} else if (t->right == NULL) {
BSTree new = t->left;
// } else {
//BSTree new = joinTrees(t->left, t->right);
}
free(t);
t = new;
}
The problem is that you are declaring multiple variables that only exist within each containing conditional block. Declare the variable at the top of the function or top of the else block. Then set that same variable in each conditional block of code.
BSTree Delete(BSTree t, int item) {
BSTree new_item;
if (item < t->value) {
t->left = Delete(t->left, item);
} else if (item > t->value) {
t->right = Delete(t->right, item);
} else {
// deleting item
if (t->left == NULL && t->right == NULL) {
new_item = NULL;
} else if (t->left == NULL) {
new_item = t->right;
} else if (t->right == NULL) {
new_item = t->left;
// } else {
//BSTree new = joinTrees(t->left, t->right);
}
free(t);
t = new_item;
}
I am trying to implement Binary search tree in C.
But I am stuck at the delete operation, when I run the code it doesn't delete the value specified.
Before calling delete:(calling inorder())
16 19 23
After calling delete:(calling inorder())
16 19 23
code:
void deleteNode(struct node *n, int data)
{
struct node *temp;
if(n->data==data)
{
if(n->left == NULL && n->right == NULL)
{
n=NULL;
}
else if(n->left == NULL && n->right!=NULL)
{
n->data = (n->right)->data;
n->right = NULL;
}
else if(n->left!=NULL && n->right == NULL)
{
n->data = (n->left)->data;
n->left=NULL;
}
else if(n->left != NULL && n->right != NULL)
{
temp = findMax(root);
n->data = temp->data;
temp = NULL;
}
}
else if(n->data > data)
{
deleteNode(n->left, data);
}
else if(n->data < data)
{
deleteNode(n->right, data);
}
}
I have other code which is working, but I want to know what is wrong with this code?
Edit:
I have edited the code with a few changes in it.
Now, When I try to delete the ROOT node.
I end up with this:
(inorder traversal)-> 16 23 23
Now,
Why is this happening when temp = NULL is making the maximum node NULL.
Note: I am not initializing temp as the code has been changed and it is initialized just before its use (temp = findMax(root)).
code inorder():
void inorder(struct node *root)
{
if(root!=NULL)
{
inorder(root->left);
printf("%d\n", root->data);
inorder(root->right);
}
}
Use this alternative code or use your temp tree in your method
struct node *temp = n; //then use temp tree in code
Alternative method
struct node *delete(struct node *tree, int data)
{
if(find(tree,data)==-1 || tree == NULL)
return tree;
if(tree->data == data)
{
if(tree->left==NULL && tree->right==NULL)
return NULL;
if(tree->right != NULL){
tree->data = min(tree->right);
tree->right = delete(tree->right,min(tree->right));
return tree;
}
tree->data = madata(tree->left);
tree->left = delete(tree->left,madata(tree->left));
return tree;
}
if(tree->data < data)
{
tree->right= delete(tree->right,data);
return tree;
}
tree->left= delete(tree->left,data);
return tree;
}
This is what worked for me,
struct node* deleteNode(struct node *n, int data)
{
struct node *temp;
temp = n;
if(n->data==data)
{
if(n->left == NULL && n->right == NULL)
{
n=NULL;
return NULL;
}
else if(n->left == NULL && n->right!=NULL)
{
n = n->right;
temp = NULL;
}
else if(n->left!=NULL && n->right == NULL)
{
n = n->left;
temp = NULL;
}
else if(n->left != NULL && n->right != NULL)
{
temp = findMax(root);
n->data = temp->data;
temp = NULL;
}
}
else if(n->data > data)
{
n->left = deleteNode(n->left, data);
}
else if(n->data < data)
{
n->right = deleteNode(n->right, data);
}
return n;
}
I learnt AVL tree from Data Structures and Algorithms Analysis in C, I typed code myself, and its insertion function cannot work well.
I checked these functions with many data. Some nodes cannot be inserted and some nodes are inserted randomly. Unsorted, I mean.
Here is part of my code:
AVLTree.h:
/* Data structures model */
typedef int data_type;
typedef struct avlnode {
data_type data;
int height;
struct avlnode *lchild;
struct avlnode *rchild;
} AvlNode;
typedef AvlNode AvlTree;
/* Function Prototypes including init, find(custom/min/max) and insert */
AvlTree *AVL_create(data_type value);
AvlNode *AVL_find(AvlTree *tree, data_type value);
AvlNode *AVL_find_min(AvlTree *tree);
AvlTree *AVL_find_max(AvlTree *tree);
AvlTree *AVL_insert(AvlTree *tree, data_type value);
#define MAX_HEIGHT(x,y) (x > y) ? x : y
AVLTree.c
/* Static function to get the height of a node in the tree */
static int height(AvlNode *node) {
return (node == NULL) ? -1 : node->height;
}
/* Tree init func with a valued root node */
AvlTree *AVL_create(data_type value) {
AvlTree *newtree;
newtree = (AvlTree *)malloc(sizeof(AvlTree));
if (newtree == NULL)
return NULL;
newtree->lchild = NULL;
newtree->rchild = NULL;
newtree->height = 0;
newtree->data = value;
return newtree;
}
/* Node search functions. In fact I use BST search functions here */
/* I'm not sure could them run well here in AVL tree */
AvlNode *AVL_find(AvlTree *tree, data_type value) {
AvlTree *temptree = tree;
if (temptree == NULL)
return NULL;
if (value < temptree->data)
return AVL_find(tree->lchild, value);
else if (value > temptree->data)
return AVL_find(tree->rchild, value);
else
return temptree;
}
AvlNode *AVL_find_min(AvlTree *tree) {
AvlTree *temptree = tree;
if (temptree != NULL) {
while (temptree->lchild != NULL)
temptree = temptree->lchild;
}
return temptree;
}
AvlTree *AVL_find_max(AvlTree *tree) {
AvlTree *temptree = tree;
if (temptree != NULL) {
while (temptree->rchild != NULL)
temptree = temptree->rchild;
}
return temptree;
}
AvlTree *AVL_insert(AvlTree *tree, data_type value) {
AvlTree *temptree = tree;
if (temptree == NULL) {
temptree = (AvlNode *)malloc(sizeof(AvlNode));
if (temptree == NULL)
return NULL;
else {
temptree->data = value;
temptree->height = 0;
temptree->lchild = NULL;
temptree->rchild = NULL;
}
}
else if (value < temptree->data) {
temptree->lchild = AVL_insert(temptree->lchild, value);
if (height(temptree->lchild) - height(temptree->rchild) == 2) {
if (value < temptree->lchild->data)
temptree = single_rotate_with_left(temptree);
else
temptree = double_rotate_with_right_left(temptree);
}
}
else if (value > temptree->data) {
temptree->rchild = AVL_insert(temptree->rchild, value);
if (height(temptree->rchild) - height(temptree->lchild) == 2) {
if (value > temptree->rchild->data)
temptree = single_rotate_with_right(temptree);
else
temptree = double_rotate_with_left_right(temptree);
}
}
temptree->height = MAX_HEIGHT(height(temptree->lchild), height(temptree->rchild)) + 1;
return temptree;
}
main.c
#include "AVLTree.h"
int main() {
AvlTree *newtree = AVL_create(50);
AVL_insert(newtree, 70);
AVL_insert(newtree, 80);
AVL_insert(newtree, 90);
for (int i = -5; i < 20; i++) {
AVL_insert(newtree, i * i * i);
}
printf("root node: %d\n", newtree->data);
printf("left of root node: %d\n", newtree->lchild->data);
printf("findmin: %d\n", AVL_find_min(newtree)->data);
printf("findmax: %d\n", AVL_find_max(newtree)->data);
return 0;
}
I have tried your program and disabled the rebalancing (see below where).
Then it works correctly, printing out:
root node: 50
left of root node: -125
findmin: -125
findmax: 6859
Which is correct I think.
So I think the problem is in one of your rotation functions.
If you can't find the problem, please show them to us.
else if (value < temptree->data) {
temptree->lchild = AVL_insert(temptree->lchild, value);
/*if (height(temptree->lchild) - height(temptree->rchild) == 2) {
if (value < temptree->lchild->data)
temptree = single_rotate_with_left(temptree);
else
temptree = double_rotate_with_right_left(temptree);
}*/
}
else if (value > temptree->data) {
temptree->rchild = AVL_insert(temptree->rchild, value);
/*if (height(temptree->rchild) - height(temptree->lchild) == 2) {
if (value > temptree->rchild->data)
temptree = single_rotate_with_right(temptree);
else
temptree = double_rotate_with_left_right(temptree);
}*/
}
I came across some threads on StackOverflow but none of them quite cleared my doubts.
So the problem is simple. I need to iteratively insert elements into a binary tree. And this is my code.
BST newNode(int x)
{
BSTNodePtr node = (BSTNodePtr) malloc(sizeof(struct TreeNode));
node->Element = x;
node->Left = NULL;
node->Right = NULL;
return node;
}
BST Insert(int x, BST T)
{
BST temp_node = T;
while( T != NULL) {
if (x < T->Element)
T = T->Left;
else if (x >= T->Element)
T = T->Right;
}
T = newNode(x);
return temp_node;
}
However, when I'm finding the height of this tree I am always getting 0. The height code is
int Height(BST T)
{
if (T == NULL)
return 0;
return 1+(max(Height(T->Left), Height(T->Right)));
}
and this works perfectly fine when I do insertion recursively (using a function with the exact same signature)
What am I missing?
Here:
BST Insert(int x, BST T)
{
BST temp_node = T;
while( T != NULL) {
if (x < T->Element)
T = T->Left;
else if (x >= T->Element)
T = T->Right;
}
T = newNode(x);
return temp_node;
}
You navigate the tree until you hit T == NULL. Then you create a node and assign the pointer to it to T. Then you return the original value of T. You don't modify your tree at all. No node in it is made to point to the newly created node. T is just a local variable.
Couldn't solve the problem that way. This code, however, seems to work.
BST Insert(int x, BST T)
{
BST temp=T;
BST node=(BST)malloc(sizeof(struct TreeNode));
node->Element=x;
node->Left=NULL;
node->Right=NULL;
if (T==NULL)
{
T=node;
return(T);
//printf("%d\n",T->Element);
}
else
{
while(1)
{
if (temp->Element>=node->Element && temp->Left==NULL)
{
temp->Left=node;
break;
}
else if (temp->Element>=node->Element && temp->Left!=NULL)
{
temp=temp->Left;
}
else if (temp->Element<node->Element && temp->Right==NULL)
{
temp->Right=node;
break;
}
else
{
temp=temp->Right;
}
}
return(T);
}
}
Here's My implementation of the aforementioned problem:
bst* newNode(int x)
{
bst* T = new bst;
T->value = x;
T->left_child = T->right_child = NULL;
return T;
}
bst* bst_insert_iter(bst* T,int val)
{
if (T == NULL)
T = newNode(val);
else
{
bst *temp_node = T;
bool flag = true;
while(flag)
{
if (val <= temp_node->value)
{
if (temp_node->left_child == NULL)
{
temp_node->left_child=newNode(val);
flag = false;
}
else
temp_node = temp_node->left_child;
}
else
{
if (temp_node->right_child == NULL)
{
temp_node->right_child=newNode(val);
flag = false;
}
else
temp_node = temp_node->right_child;
}
}
}
return T;
}
You have the bug in your insert function. As I may assume, initially your tree is empty. so the first time you insert a node, the second argument is NULL, right? Then this function always returns NULL to you as you always pass a NULL value.
template <class T>
class TreeNode{
private:
T data;
TreeNode<T>* right,*left;
public:
void setData(T d){
this->data =d;
}
T getData(){
return this->data;
}
void setRight(TreeNode<T>* r){
this->right =r;
}
TreeNode<T>* getRight(){
return this->right;
}
void setLeft(TreeNode<T>* r){
this->left =r;
}
TreeNode<T>* getLeft(){
return this->left;
}
static TreeNode<T>* newNode(T data){
TreeNode<T>* n = new TreeNode<T>();
n->setData(data);
n->setRight(NULL);
n->setLeft(NULL);
return n;
}
};
template <class T>
class BinaryTree{
private:
TreeNode<T>* root;
public:
void insert(T data){
TreeNode<T>* n = TreeNode<T>::newNode(data);
if(root==NULL)
root = n;
else{
TreeNode<T>* t = root;
while(t!=NULL){
if(n->getData() >= t->getData()){
if(t->getRight()==NULL){
t->setRight(n); //newnode attached as right child in tree
t = NULL;
}
else
t = t->getRight();
}
else{
if(t->getLeft()==NULL){
t->setLeft(n); //newnode attached as left child in tree
t=NULL;
}
else
t = t->getLeft();
}
}
}
}
void preorder(){
TreeNode<T>* t = root;
preorderUtil(t);
}
void preorderUtil(TreeNode<T>* node){
if(node==NULL)
return;
preorderUtil(node->getLeft());
cout<<node->getData()<<" ";
preorderUtil(node->getRight());
}
};
Your changes are not reflected in the tree. I followed this way to insert data iteratively and it works fine. The point is making a node inside your binarytree to point the newly created node such that it gets attached to the tree.
Here is my version , it seems to be working.
struct tree{
tree *left;
tree *right;
int key;
};
void insertBst(int k,tree *t)
{
tree *newK = new tree[sizeof(tree)];
newK->key = k;
newK->left = NULL;
newK->right = NULL;
if((t)->key == NULL)
{
t=newK;
return;
}
else{
bool found = false;
tree *root = t;
tree *parent = NULL;
while(root != NULL)
{
parent = root;
if(root->key < newK->key)
{
root=root->right;
}
else if(root->key > newK->key)
{
root=root->left;
}
else{
//Here we have duplicates!! so do nothing
root = root;
}
}
if(parent->key > newK->key) parent->left = newK;
else parent->right = newK;
}
}