Iteratively inserting into a binary tree - c

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;
}
}

Related

How can I delete a node from Binary search tree in C with 2 children

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;

Insert function for every binary tree

If i have for example 2 binary trees:
typedef struct node {
int key;
struct node *left, *right;
} node;
node* root1
node* root2
I've tried this function to insert nodes:
void insert(node* root, int key) {
node *p, *q;
p = (node*) calloc(1,sizeof(node);
p->key = key;
if (root == NULL) {
root = p;
return;
}
q = root;
for (;;) {
if (key < q->key) {
if (q->left == 0) {
q->left = p;
return;
} else q = q->left;
} else if (key > q->key) {
if (q->right == 0) {
q->right = p;
return;
} else q = q->right;
} else {
free(p);
return;
}
}
}
but after call insert(root1,10) the tree root1 remains untouched. I suppose it happens because root variable inside function is changed locally.
How i should implement the function that will receive as argument the tree in which i want to insert nodes?
You could always return a pointer to the root, like this
node* insert(node* root, int key) {
node *p, *q;
p = (node*) calloc(1,sizeof(node));
p->key = key;
if (root == NULL) {
root = p;
return root;
}
q = root;
for (;;) {
if (key < q->key) {
if (q->left == 0) {
q->left = p;
return root;
} else q = q->left;
} else if (key > q->key) {
if (q->right == 0) {
q->right = p;
return root;
} else q = q->right;
} else {
free(p);
return root;
}
}
}
And you create your tree like -
node* root1 = NULL;
root1 = insert(root1,3)

Why does afl fuzzer get segmentation fault?

I did a program in c to do some avl sorting. the program runs well when i test it with no crash. however i ran the program for possible bugs with afl fuzzer and i dont seem to know why i keep getting segmentation fault. below is the tree.c. I dont get bugs when i fuzz without my main.c connecting to the tree.c. Only comes when i send inputs to the tree sorter. Some certain inputs brings about this bug. i made changes to memory allocation but still cant figure out why. i used valgrind, cppcheck and dont get any errors on them. Please why does this error happen and how can i fix it?
an example input from the fuzzer that brings code to segmentation fault
i 3o
i 7ÿo
i
i 3ÿo
i3
3
i 3ÿ3
i83 3
i23ÿo
tree.c
#include "tree.h"
Tree* tree_create(){
Tree *tree = malloc(sizeof(Tree));
tree->root = NULL;
return tree;
}
void tree_node_delete(Node* node) {
if (node == NULL) {
free(node);
return;
}
if (node->left) {
tree_node_delete(node->left);
}
if (node->right) {
tree_node_delete(node->right);
}
free(node->name);
free(node);
}
void tree_delete(Tree* tree) {
tree_node_delete(tree->root);
free(tree);
}
void node_insert(Node* node, int age, char* name, int gen) {
if (age <= node->age){
if (node->left == NULL){
Node* newLeft = calloc(1, sizeof(Node));
newLeft->age = age;
newLeft->name = name;
newLeft->parent = node;
newLeft->right = NULL;
newLeft->left = NULL;
newLeft->isRight = false;
node->left = newLeft;
} else {
node_insert(node->left, age, name, node->left->generation);
}
} else {
if (node->right == NULL){
Node* newRight = calloc(1, sizeof(Node));
newRight->age = age;
newRight->name = name;
newRight->parent = node;
newRight->right = NULL;
newRight->left = NULL;
newRight->isRight = true;
node->right = newRight;
} else {
node_insert(node->right, age, name, node->right->generation);
}
}
}
void tree_insert(Tree* tree, int age, char* name) {
if (tree->root == NULL) {
Node *node = calloc(1, sizeof(Node));
node->name = name;
node->age = age;
node->isRoot = true;
node->right = NULL;
node->left = NULL;
tree->root = node;
} else {
node_insert(tree->root, age, name, 1);
}
}
void tree_erase(Tree* tree, int age, char* name) {
Node* data = tree_find(tree, age, name);
if (data == NULL) {
printf("\nThis node doesn't exist in the current tree\n");
} else {
data->name = NULL;
data->age = NULL;
if (data->grandparent) {
if(data == data->grandparent->grandchildRR) {
data->grandparent->grandchildRR = NULL;
} else if(data == data->grandparent->grandchildRL) {
data->grandparent->grandchildRL = NULL;
} else if(data == data->grandparent->grandchildLR) {
data->grandparent->grandchildLR = NULL;
} else if(data == data->grandparent->grandchildLL) {
data->grandparent->grandchildLL = NULL;
}
}
tree_cleanup(tree, &tree->root, tree->root);
}
}
// Will clean the tree to release previously used nodes
void tree_cleanup(Tree* tree, Node** nodeAdress, Node* node) {
if (node->left) {
tree_cleanup(tree, &node->left, node->left);
}
if (node->right) {
tree_cleanup(tree, &node->right, node->right);
}
if(node->age == NULL && node->name == NULL) {
*nodeAdress = NULL;
free(*nodeAdress);
}
if(node->left == NULL && node->grandchildLL) {
node->left = node->grandchildLL;
node->left->parent = node;
node->left->grandparent = node->parent;
if(node->left->left) {
node->grandchildLL = node->left->left;
} else {
node->grandchildLL = NULL;
}
} else if(node->right == NULL && node->grandchildRL) {
node->right = node->grandchildRL;
node->right->parent = node;
node->right->grandparent = node->parent;
node->right->isRight = true;
if(node->right->left) {
node->grandchildRL = node->right->left;
} else {
node->grandchildLR = NULL;
}
} else if(node->left == NULL && node->grandchildLR) {
node->left = node->grandchildLR;
node->left->parent = node;
node->left->grandparent = node->parent;
node->left->isRight = false;
if (node->left->right) {
node->grandchildLR = node->left->right;
} else {
node->grandchildLR = NULL;
}
} else if(node->right == NULL && node->grandchildRR) {
node->right = node->grandchildRR;
node->right->parent = node;
node->right->grandparent = node->parent;
if (node->right->right) {
node->grandchildRR = node->right->right;
} else {
node->grandchildRR = NULL;
}
}
}
//Calculate the weight and the balance factor of the node.
void tree_balance_factor(Tree* tree, Node* node) {
if (node == NULL) {
return;
}
if (node->left) {
tree_balance_factor(tree, node->left);
}
if (node->right) {
tree_balance_factor(tree, node->right);
}
if (node->parent) {
if (node->isRight == true) {
if (node->weightRight > node->weightLeft) {
node->parent->weightRight = node->weightRight+1;
} else {
node->parent->weightRight = node->weightLeft+1;
}
} else if (node->isRight == false) {
if (node->weightRight > node->weightLeft) {
node->parent->weightLeft = node->weightRight+1;
} else {
node->parent->weightLeft = node->weightLeft+1;
}
}
}
node->balancefactor = node->weightRight - node->weightLeft;
if (node->balancefactor == 2) {
if(node->right->balancefactor == 1) {
leftRotation(tree, node);
} else {
rightPermutation(tree, node);
leftRotation(tree, node);
}
} else if (node->balancefactor == -2) {
if(node->left->balancefactor == -1) {
rightRotation(tree, node);
} else {
leftPermutation(tree, node);
rightRotation(tree, node);
}
}
}
// Reset the weightings and set up the grandchilds and grandparents relations back
void tree_balance_factor_reset(Tree* tree, Node* node) {
if (node == NULL) {
return;
}
if (node->left) {
tree_balance_factor_reset(tree, node->left);
}
if (node->right) {
tree_balance_factor_reset(tree, node->right);
}
node->weightLeft = 0;
node->weightRight = 0;
if(node->right) {
if(node->right->right) {
node->grandchildRR = node->right->right;
node->right->parent = node;
node->right->right->grandparent = node;
} else {
node->grandchildRR = NULL;
}
if(node->right->left) {
node->grandchildRL = node->right->left;
node->right->parent = node;
node->right->left->grandparent = node;
} else {
node->grandchildRL = NULL;
}
}
if(node->left) {
if(node->left->left) {
node->grandchildLL = node->left->left;
node->left->parent = node;
node->left->left->grandparent = node;
} else {
node->grandchildLL = NULL;
}
if (node->left->right) {
node ->grandchildLR = node->left->right;
node->left->parent = node;
node->left->right->grandparent = node;
} else {
node->grandchildLR = NULL;
}
}
}
void setGen (Node* node) {
if(node->parent) {
node->generation = node->parent->generation +1;
}
if (node->left) {
setGen(node->left);
}
if (node->right) {
setGen(node->right);
}
}
void leftRotation(Tree* tree, Node* node ) {
Node* newNode = node->right;
if(node->isRoot == true) {
tree->root = newNode;
newNode->isRoot = true;
node->isRoot = false;
newNode->parent = NULL;
} else if (node->isRoot = false){
newNode->parent = node->parent;
if(node->isRight) {
newNode->parent->right = newNode;
} else {
newNode->parent->left = newNode;
}
}
newNode->left = node;
node->parent = newNode;
node->right = NULL;
}
void rightRotation(Tree* tree, Node* node) {
Node* newNode = node->left;
if(node->isRoot == true) {
tree->root = newNode;
newNode->isRoot = true;
node->isRoot = false;
newNode->parent = NULL;
} else {
newNode->parent = node->parent;
if(node->isRight) {
newNode->parent->right = newNode;
} else {
newNode->parent->left = newNode;
}
}
newNode->right = node;
node->parent = newNode;
node->left = NULL;
}
void rightPermutation(Tree* tree, Node* node) {
Node* newNode = node->right;
node->right = newNode->left;
node->right->right = newNode;
newNode->left = NULL;
newNode->parent = node->right;
node->right->parent = node;
}
void leftPermutation(Tree* tree, Node* node) {
Node* newNode = node->left;
node->left = newNode->right;
node->left->left = newNode;
newNode->right = NULL;
newNode->parent = node->left;
node->left->parent = node;
}
void tree_print_node(Node* node){
if (node == NULL) {
printf("null");
return;
}
printf("[");
printf("{\"%d\":\"%s\"},", node->age, node->name);
tree_print_node(node->left);
printf(",");
tree_print_node(node->right);
printf("]");
}
void tree_print(Tree* tree, int printNewline){
if (tree == NULL) {
printf("null");
return;
}
tree_print_node(tree->root);
if (printNewline){
printf("\n");
}
}
Node* node_find(Node* node, int age, char* name) {
int i = strcmp(node->name, name);
if (node->age == age && i == 0) {
return node;
}
if (age <= node->age) {
if (node->left) {
return node_find(node->left, age, name);
} else {
return NULL;
}
} else {
if (node->right) {
return node_find(node->right, age, name);
} else {
return NULL;
}
}
}
Node* tree_find(Tree* tree, int age, char* name) {
if(tree->root != NULL) {
return node_find(tree->root, age, name);
} else {
printf("\nNo node inserted in the tree yet\n");
return NULL;
}
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "main.h"
#include "tree.h"
int main() {
char* commandBuffer = (char*)malloc(sizeof(char) * 20);
Tree *tree = tree_create();
for(;;) {
if (tree == NULL){
tree = tree_create();
}
tree_balance_factor_reset(tree, tree->root);
tree_balance_factor(tree, tree->root);
tree_balance_factor_reset(tree, tree->root);
printf("\n- Enter <i age name> to insert a node in the tree \n- Enter <e age name> to erase a node \n- Enter <c age name> to check the tree \n- Enter <p> to "
"print the tree \n- Enter <x> the delete the tree \n- Enter <q> to exit the program\n\n" );
fgets(commandBuffer, 20, stdin);
int b = strlen(commandBuffer);
if(b>=19) {
int clearVar;
while (((clearVar = getchar()) != '\n' && clearVar != EOF)) {
}
};
// Quit on EOF or 'q'
if (feof(stdin) || *commandBuffer == 'q' ){
break;
}
tree = handleString(commandBuffer, tree);
};
free(tree);
free(commandBuffer);
return 0;
}
Tree* handleString(char command[], Tree *tree){
if (command == NULL){
fprintf(stderr, "Invalid command; null pointer\n");
return tree;
}
switch(command[0]){
case 'i':
insert(command, tree);
break;
case 'e':
erase(command, tree);
break;
case 'c':
check(command, tree);
break;
case 'p':
tree_print(tree, 1);
break;
case 'x':
tree_delete(tree);
return NULL;
default:
fprintf(stderr, "Invalid command string: %s\n", command);
break;
}
return tree;
}
Tree* insert(char* command, Tree* tree) {
int age;
char* name = malloc(sizeof(char) * 20);
if (2 != sscanf(command, "i %d %19s", &age, name)){
fprintf(stderr, "Failed to parse insert command: not enough parameters filled\n");
// return NULL;
}
if (tree == NULL){
tree = tree_create();
}
tree_insert(tree, age, name);
return tree;
}
int erase(char* command, Tree* tree) {
int age;
char* name = malloc(sizeof(char) * 20);
if (2 != sscanf(command, "e %d %19s", &age, name)){
fprintf(stderr, "Failed to parse erase command: not enough parameters filled\n");
// return 0;
}
tree_erase(tree, age, name);
return 0;
}
void check(char* command, Tree* tree) {
int age;
char* name = malloc(sizeof(char) * 20);
if (2 != sscanf(command, "c %d %19s", &age, name)){
fprintf(stderr, "Failed to parse check command\n");
}
Node* result = tree_find(tree, age, name);
if (result){
printf("\nThe node is present\n");
} else {
printf("\nThe node could not be found\n");
}
}
tree.h
#ifndef C_IMPLEMENTATION_TREE_H
#define C_IMPLEMENTATION_TREE_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct Node {
/**
* Left child of this node
*/
struct Node* left;
/**
* Right child of this node
*/
struct Node* right;
/**
* The age of the data in this node
*/
int generation;
int balancefactor;
int weightLeft;
int weightRight;
struct Node* parent;
struct Node* grandparent;
struct Node* grandchildLL;
struct Node* grandchildLR;
struct Node* grandchildRL;
struct Node* grandchildRR;
bool isRight;
bool parentIsRight;
bool isRoot;
int age;
/**
* The name of the data in this node
*/
char* name;
} Node;
typedef struct Tree {
Node *root;
} Tree;
/**
* Create a new tree
* #param age The age value for the first data point
* #param name The name value for the first data point
* #return The root Node of the tree
*/
Tree* tree_create();
/**
* Delete an entire tree. This will delete the passed Node and all children below it
* #param node The root Node of the tree to delete.
*/
void tree_delete(Tree* tree);
/**
* Insert a new data point into the tree
*
* #param tree The root node of the tree
* #param age The age part of the data point
* #param name The name part of the data point
*/
void tree_insert(Tree* tree, int age, char* name);
/**
* Remove a data point from a tree
* #param tree The root node of the tree
* #param age The age part of the data point to delete
* #param name The name part of the data point to delete
*/
void tree_erase(Tree* tree, int age, char* name);
/**
* Prints a tree in the following format:
* [<data>, <left>, <right>]
* where the elements above have the following format:
* <data> {<age:int>: "<name:string>"}
* <left>, <right>: The same format as the root node. When a child node is NULL, the string NULL is to be printed.
*/
void tree_cleanup(Tree* tree, Node** nodeAdress, Node* node);
/**
* Will free and release null nodes.
*/
void setGen(Node* node);
void tree_balance_factor(Tree* tree,Node* node);
void tree_balance_factor_reset(Tree* tree, Node* node);
void leftRotation(Tree* tree, Node* node);
void rightRotation(Tree* tree,Node* node);
void rightPermutation(Tree* tree, Node* node);
void leftPermutation(Tree* tree, Node* node);
void tree_print(Tree *tree, int printNewline);
Node* tree_find(Tree* node, int age, char* name);
#endif //C_IMPLEMENTATION_TREE_H
I managed to reproduce SIGSEGV in gdb. It is hapened in function rightPermutation, which does not check if pointer to left is NULL or not:
void rightPermutation(Tree* tree, Node* node) {
Node* newNode = node->right;
node->right = newNode->left;
In case the node->left is NULL, you will get SIGSEGV on next line:
node->right->right = newNode;
Further, you can see details of the message and data of the Node structure.
Program received signal SIGSEGV, Segmentation fault.
0x000055555555570c in rightPermutation (tree=0x555555758280, node=0x555555758d20) at tree.c:322
322 node->right->right = newNode;
(gdb) p node
$1 = (Node *) 0x555555758d20
(gdb) p *node
$2 = {left = 0x555555758ed0, right = 0x0, generation = 0, balancefactor = 2, weightLeft = 1, weightRight = 3, parent = 0x0, grandparent = 0x555555758b70,
grandchildLL = 0x0, grandchildLR = 0x0, grandchildRL = 0x0, grandchildRR = 0x555555758c00, isRight = false, parentIsRight = false, isRoot = true, age = 0,
name = 0x555555758d00 ""}

Delete function of a binary search tree not working properly

This is a delete function of a binary search tree coded in C, but this is not working properly. The node which is supposed to be deleted is replaced by a garbage value.
void delete(struct node* root,int data)
{
{
struct node* t1;
if(root==0) {
printf("element not found\n");
} else if(data>root->data) {
delete(root->right,data);
} else if(data<root->data) {
delete(root->left,data);
} else {
if(root->right&&root->left) {
t1=findmin(root->right);
root->data=t1->data;
free(t1);
} else {
t1=root;
if(root->right) {
root=root->right;
} else if(root->left) {
root=root->left;
}
free(t1);
}
}
}
it is working per se, but the node is not getting deleted and is replaced by some garbage value.
struct node* findmin(struct node* t) {
if(t==NULL) {
return NULL;
} else if(t->left) {
findmin(t->left);
} else
return t;
}
You are passing root in the function parameters and then inside the following block of your code you are reassigning it.
else
{
t1=root;
if(root->right)
{
root=root->right;
}
else if(root->left)
{
root=root->left;
}
free(t1);
}
This reassignment is temporary to current function call (because it's been passed by value).
alternatively you can do the same is by returning the new root of the tree after deletion of the specified node.
struct node* delete(struct node* root, int key)
{
if (root == NULL) return root;
if (key < root->key)
root->left = delete(root->left, key);
else if (key > root->key)
root->right = delete(root->right, key);
else
{
// node with only one child or no child
if (root->left == NULL)
{
struct node *temp = root->right;
free(root);
return temp;
}
else if (root->right == NULL)
{
struct node *temp = root->left;
free(root);
return temp;
}
struct node* temp = findmin(root->right);
root->key = temp->key;
root->right = delete(root->right, temp->key);
}
return root;
}

AVL Tree insertion (in C) failed

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);
}*/
}

Resources