As I try to delete some items from my AVL tree, I'm losing as result some other items. You can see this from the example in the picture.
What is wrong with my code?
#include <stdio.h>
#include <stdlib.h>
typedef struct Tree{
int key;
struct Tree *left,*right;
int height;
}tree;
int height(tree *t)
{
if (t == NULL)
return 0;
return t->height;
}
int getBalance(tree *t)
{
if(t==NULL)
return 0;
return height(t->left)-height(t->right);
}
int max(int a, int b)
{
return (a > b)? a : b;
}
tree* newNode(int key)
{
tree* node = (tree*)malloc(sizeof(tree));
node->key = key;
node->left = NULL;
node->right = NULL;
node->height = 1; // new node is initially added at leaf
return(node);
}
tree* insert(tree* node, int key)
{
/* 1. Perform the normal BST rotation */
if (node == NULL)
return(newNode(key));
if (key < node->key)
node->left = insert(node->left, key);
else
node->right = insert(node->right, key);
/* 2. Update height of this ancestor node */
node->height = max(height(node->left), height(node->right)) + 1;
return node;
}
void print_preorder(tree * tTree)
{
if(tTree)
{
printf("%d ",tTree->key);
print_preorder(tTree->left);
print_preorder(tTree->right);
}
}
void deleteTree(tree * tTree)
{
if (tTree)
{
deleteTree(tTree->left);
deleteTree(tTree->right);
free(tTree);
}
}
tree* minItem(tree *tTree) /* delete */
{
if(tTree->left)
{
tTree = tTree->left;
}
else;
return tTree;
}
tree* del(tree *tTree, int delItem) /* delete( main body) */
{
if(!(tTree))
return tTree;
if(delItem < tTree->key)
tTree->left = del(tTree->left, delItem);
else
if(delItem > tTree->key)
tTree->right = del(tTree->right, delItem);
else
if((tTree->left) && (tTree->right))
{
tree *tmp=minItem(tTree->right);
tTree->key = tmp->key;
if(tTree->right->left)
tTree->right = del(tTree->right,tTree->right->left->key);
else tTree->right = del(tTree->right,tTree->right->key);
}
else
if(tTree->left)
tTree = tTree->left;
else
tTree = tTree->right;
return tTree;
}
tree* rotateLeft(tree* t)
{
tree *y = t->right;
tree *T2 = y->left;
// Perform rotation
y->left = t;
t->right = T2;
// Update heights
t->height = max(height(t->left), height(t->right))+1;
y->height = max(height(y->left), height(y->right))+1;
// Return new root
return y;
}
tree* rotateRight(tree* t)
{
tree *x = t->left;
tree *T2 = x->right;
// Perform rotation
x->right = t;
t->left = T2;
// Update heights
t->height = max(height(t->left), height(t->right))+1;
x->height = max(height(x->left), height(x->right))+1;
// Return new root
return x;
}
tree *balanceNode(tree *t)
{
if (!t) return t;
int balance = getBalance(t);
if (balance > 1 && getBalance(t->left) >= 0) /* rotateReight */
return rotateRight(t);
if (balance < -1 && getBalance(t->right) <= 0) /* rotateLeft */
return rotateLeft(t);
if (balance > 1 && getBalance(t->left) < 0) /* rotateLeftReight */
{
t->left = rotateLeft(t->left);
return rotateRight(t);
}
if (balance < -1 && getBalance(t->right) > 0) /* rotateReightLeft */
{
t->right = rotateRight(t->right);
return rotateLeft(t);
}
return t;
}
int main()
{
tree *Tree, *delTree;
Tree = NULL; delTree = NULL;
int i, a[]={7,3,9,10,8,1,4,2,6,5};
for(i=0;i<10;i++) /* construct tree */
Tree = insert(Tree,a[i]);
/* Printing nodes of tree */
printf("Pre Order Display\n");
print_preorder(Tree);
printf("\nBalanced Tree\n");
Tree=balanceNode(Tree);
print_preorder(Tree);
while(1)
{
printf("\nEnter an Item that You Want to Delete: ");
scanf("%d",&i);
printf("\n");
delTree = del(Tree,i);
delTree = balanceNode(delTree);
/* Pre-order displays root node, left node and then right node. */
print_preorder(delTree);
}
printf("\n");
deleteTree(Tree);
deleteTree(delTree);
printf("\n");
return 0;
}
It would probably be best if you figure it out yourself. The print_preorder function could be useful for debugging your code.
The tricky part of the deletion is this code, so you could trace what's happpening there:
if((tTree->left) && (tTree->right))
{
tree *tmp=minItem(tTree->right);
tTree->key = tmp->key;
if(tTree->right->left)
tTree->right = del(tTree->right,tTree->right->left->key);
else tTree->right = del(tTree->right,tTree->right->key);
}
This version seems to work:
#include <stdio.h>
#include <stdlib.h>
typedef struct Tree{
int key;
struct Tree *left,*right;
int height;
}tree;
int height(tree *t)
{
if (t == NULL)
return 0;
return t->height;
}
int getBalance(tree *t)
{
if(t==NULL)
return 0;
return height(t->left)-height(t->right);
}
int max(int a, int b)
{
return (a > b)? a : b;
}
tree* newNode(int key)
{
tree* node = (tree*)malloc(sizeof(tree));
node->key = key;
node->left = NULL;
node->right = NULL;
node->height = 1; // new node is initially added at leaf
return(node);
}
tree* insert(tree* node, int key)
{
/* 1. Perform the normal BST rotation */
if (node == NULL)
return(newNode(key));
if (key < node->key)
node->left = insert(node->left, key);
else
node->right = insert(node->right, key);
/* 2. Update height of this ancestor node */
node->height = max(height(node->left), height(node->right)) + 1;
return node;
}
void print_preorder(tree * tTree)
{
if(tTree)
{
printf("%d ",tTree->key);
print_preorder(tTree->left);
print_preorder(tTree->right);
}
}
void deleteTree(tree * tTree)
{
if (tTree)
{
deleteTree(tTree->left);
deleteTree(tTree->right);
free(tTree);
}
}
tree* del(tree *tTree, int delItem) /* delete( main body) */
{
if(!(tTree))
return tTree;
if(delItem < tTree->key)
tTree->left = del(tTree->left, delItem);
else
if(delItem > tTree->key)
tTree->right = del(tTree->right, delItem);
else
{
tree *oTree = tTree;
if((tTree->left) && (tTree->right))
{
tree *parent = tTree->right;
tTree = parent->left;
if (tTree)
{
while(tTree->left)
{
parent = tTree;
tTree = tTree->left;
}
parent->left = tTree->right;
tTree->right = oTree->right;
}
else
tTree = parent;
tTree->left = oTree->left;
}
else
if(tTree->left)
tTree = tTree->left;
else
tTree = tTree->right;
free(oTree);
}
return tTree;
}
tree* rotateLeft(tree* t)
{
tree *y = t->right;
tree *T2 = y->left;
// Perform rotation
y->left = t;
t->right = T2;
// Update heights
t->height = max(height(t->left), height(t->right))+1;
y->height = max(height(y->left), height(y->right))+1;
// Return new root
return y;
}
tree* rotateRight(tree* t)
{
tree *x = t->left;
tree *T2 = x->right;
// Perform rotation
x->right = t;
t->left = T2;
// Update heights
t->height = max(height(t->left), height(t->right))+1;
x->height = max(height(x->left), height(x->right))+1;
// Return new root
return x;
}
tree *balanceNode(tree *t)
{
if (!t) return t;
int balance = getBalance(t);
if (balance > 1 && getBalance(t->left) >= 0) /* rotateReight */
return rotateRight(t);
if (balance < -1 && getBalance(t->right) <= 0) /* rotateLeft */
return rotateLeft(t);
if (balance > 1 && getBalance(t->left) < 0) /* rotateLeftReight */
{
t->left = rotateLeft(t->left);
return rotateRight(t);
}
if (balance < -1 && getBalance(t->right) > 0) /* rotateReightLeft */
{
t->right = rotateRight(t->right);
return rotateLeft(t);
}
return t;
}
int main(void)
{
tree *Tree;
Tree = NULL;
int i, a[]={7,3,9,10,8,1,4,2,6,5};
for(i=0;i<10;i++) /* construct tree */
Tree = insert(Tree,a[i]);
/* Printing nodes of tree */
printf("Pre Order Display\n");
print_preorder(Tree);
printf("\nBalanced Tree\n");
Tree=balanceNode(Tree);
print_preorder(Tree);
while(1)
{
printf("\nEnter an Item that You Want to Delete: ");
scanf("%d",&i);
printf("\n");
Tree = del(Tree,i);
printf("After Delete\n");
/* Pre-order displays root node, left node and then right node. */
print_preorder(Tree);
Tree = balanceNode(Tree);
printf("\nAfter Balance\n");
print_preorder(Tree);
}
printf("\n");
deleteTree(Tree);
printf("\n");
return 0;
}
yeah! I've used a new variable "delTree" to delete a node from my tree, but if I use the same "Tree" instead of "delTree" it will be OK, what I needed
do
{
printf("\nEnter an Item that You Want to Delete: ");
scanf("%d",&i);
printf("\n");
Tree = del(Tree,i);
Tree = balanceNode(Tree);
print_preorder(Tree);
i--;
}while(i);
Thanks to all!
Related
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)
Creating a dictionary comparison program utilizing avl_tree, but getting a segfault when reading in a large file 200,000+ unique words. Smaller files seem to work fine.
A couple of my thoughts might be my word_compre function which may interfere with the rotation. Or likely I have implemented the rotation incorrectly.
// String compare based on alphabetical order
int word_compare(char *word, struct tree_node *root)
{
return strcasecmp(word, root->word);
}
// Get the maximum of two integers
int get_max(int int_a, int int_b)
{
if (int_a > int_b)
return int_a;
else
return int_b;
}
// Get the height of the tree
int get_height(struct tree_node *root)
{
if (root == NULL)
return 0;
else
return root->height;
}
// Determine if the tree or subtree is unbalanced by comparing the max height
// of the left and right branches
int get_balance(struct tree_node *root)
{
if (root == NULL)
return 0;
else
return get_height(root->left) - get_height(root->right);
}
// Rotate left subtree rooted with right child node
struct tree_node *left_rotate(struct tree_node* root)
{
// Store the right child node to rotate
struct tree_node *right_child = root->right;
// Store the left of the right child node to rotate
struct tree_node *subtree = right_child->left;
// Perform rotation
right_child->left = root;
root->right = subtree;
// Update heights
root->height = get_max(get_height(root->left),
get_height(root->right)) + 1;
right_child->height = get_max(get_height(right_child->left),
get_height(right_child->right)) + 1;
return right_child;
}
// Rotate right subtree rooted with left child node
struct tree_node *right_rotate(struct tree_node *root)
{
// Store the left child node to rotate
struct tree_node *left_child = root->left;
// Store the right of the left child node to rotate
struct tree_node *subtree = left_child->right;
// Perform rotation
left_child->right = root;
root->left = subtree;
// Update heights
root->height = get_max(get_height(root->left),
get_height(root->right)) + 1;
left_child->height = get_max(get_height(left_child->left),
get_height(left_child->right)) + 1;
return left_child;
}
// Insert new node into a tree
struct tree_node *insert_node(struct tree_node *root, char *word, int fp_num)
{
// Viable spot found, insert a new node
if (root == NULL) {
#ifdef DEBUG
printf("INSERTED NODE\n");
printf("WORD: %s\n", word);
#endif
if (fp_num == 1) {
// Allocate a new node
root = (struct tree_node *)malloc(sizeof(struct tree_node));
// Fail to allocate a new node
if (root == NULL) {
printf("\nFailed to allocate a node\n");
return NULL;
}
// Initialize the new node
else {
root->word = strdup(word);
root->count = 1;
root->left = NULL;
root->right = NULL;
root->height = 1;
return root;
}
}
else {
return root;
}
}
int exist = word_compare(word, root);
if (exist < 0) {
root->left = insert_node(root->left, word, fp_num);
}
else if (exist > 0) {
root->right = insert_node(root->right, word, fp_num);
}
else {
if (fp_num != 1 && root->count == fp_num - 1) {
root->count = fp_num;
}
}
// Check the balance of the tree
int balance = get_balance(root);
// If the tree is imbalanced, fixed them with one of the following cases
// Left-Left-Case
if (balance > 1 && (word_compare(word, root->left) < 0))
return right_rotate(root);
// Right-Right-Case
if (balance < -1 && (word_compare(word, root->right) > 0))
return left_rotate(root);
// Left-Right-Case
if (balance > 1 && (word_compare(word, root->left) > 0)) {
root->left = left_rotate(root->left);
return right_rotate(root);
}
// Right-Left-Case
if (balance < -1 && (word_compare(word, root->right) < 0)) {
root->right = right_rotate(root->right);
return left_rotate(root);
}
return root;
}
// Perform in-order traversal sort of the tree and display results
void in_order(struct tree_node *root, int fp_num)
{
if (root == NULL)
return;
// Recur until the left most node
if (root->left)
in_order(root->left, fp_num);
// Find the amount of dollars from the cents and puts the
// remainder after a decimal point
if (fp_num != 1 && root->count == fp_num)
printf("%s\n", root->word);
// Recur until the right most node
if (root->right)
in_order(root->right, fp_num);
}
// Delete tree
void free_tree(struct tree_node *root)
{
if (root != NULL)
{
free_tree(root->left);
free(root->word);
free_tree(root->right);
free(root);
}
}
Fixed it. Did not update current node/root height in the insertion function.
// Insert new node into a tree
struct tree_node *insert_node(struct tree_node *root, char *word, int fp_num)
{
// Viable spot found, insert a new node
if (root == NULL) {
#ifdef DEBUG
printf("INSERTED NODE\n");
printf("WORD: %s\n", word);
#endif
if (fp_num == 1) {
// Allocate a new node
root = (struct tree_node *)malloc(sizeof(struct tree_node));
// Fail to allocate a new node
if (root == NULL) {
printf("\nFailed to allocate a node\n");
return NULL;
}
// Initialize the new node
else {
root->word = strdup(word);
root->count = 1;
root->left = NULL;
root->right = NULL;
root->height = 1;
return root;
}
}
else {
return root;
}
}
int word_exist = word_compare(word, root);
if (word_exist < 0) {
root->left = insert_node(root->left, word, fp_num);
}
else if (word_exist > 0) {
root->right = insert_node(root->right, word, fp_num);
}
else {
if (fp_num != 1 && root->count == fp_num - 1) {
root->count = fp_num;
}
}
// Update height of current node
root->height = 1 + get_max(get_height(root->left), get_height(root->right));
// Check the balance of the tree
int balance = get_balance(root);
// If the tree is imbalanced, fixed them with one of the following cases
// Left-Left-Case
if (balance > 1 && (word_compare(word, root->left) < 0))
return right_rotate(root);
// Right-Right-Case
if (balance < -1 && (word_compare(word, root->right) > 0))
return left_rotate(root);
// Left-Right-Case
if (balance > 1 && (word_compare(word, root->left) > 0)) {
root->left = left_rotate(root->left);
return right_rotate(root);
}
// Right-Left-Case
if (balance < -1 && (word_compare(word, root->right) < 0)) {
root->right = right_rotate(root->right);
return left_rotate(root);
}
return root;
}
I am trying to add numbers in AVL Tree where the node takes (key, value). When entering numbers from (0,0) to (10,10) in the for loop, the code fails when it tries to enter the number (10,10).
Following is the code to insert the node in the tree:
int insert_in_tree_q5(struct AVLTreeNode **node, int key, int value){
//AVLTreeNode *newNode = newAVLTreeNode(key, value);
// if the tree is empty
if(*node == NULL){
*node = newAVLTreeNode(key, value);
}
if(key != (*node)->key){
// insert on left if the data in the key is less than the data in the node.
if (key<(*node)->key){
insert_in_tree_q5(&(*node)->left, key,value);
}
// insert on right if the data in the key is greater than the data in the node.
else if(key>(*node)->key)
{
insert_in_tree_q5(&(*node)->right, key,value);
}
// Update height of the ancestor node
(*node)->height = 1 + max(height((*node)->left), height((*node)->right));
// check balance to see if this node became unbalanced
int balance = getBalance(*node);
//First case to balance the unbalanced node
// Left Left case
if(balance>1 && key<(*node)->left->key){
*node = rightRotate(*node);
}
// Right Right Case
if (balance < -1 && key > (*node)->right->key)
*node = leftRotate(*node);
// Left Right Case
if (balance > 1 && key > (*node)->left->key)
{
(*node)->left = leftRotate((*node)->left);
*node = rightRotate(*node);
}
// Right Left Case
if (balance < -1 && key < (*node)->right->key)
{
(*node)->right = rightRotate((*node)->right);
*node = leftRotate(*node);
}
}
else if(key == (*node)->key){
if (value<(*node)->value){
insert_in_tree_q5(&(*node)->left, key,value);
}
// insert on right if the data in the key is greater than the data in the node.
else if(value>(*node)->value)
{
insert_in_tree_q5(&(*node)->right, key,value);
}
// Update height of the ancestor node
(*node)->height = 1 + max(height((*node)->left), height((*node)->right));
// check balance to see if this node became unbalanced
int balance = getBalance(*node);
//First case to balance the unbalanced node
// Left Left case
if(balance>1 && value<(*node)->left->value){
*node =rightRotate(*node);
}
// Right Right Case
if (balance < -1 && value > (*node)->right->value)
*node =leftRotate(*node);
// Left Right Case
if (balance > 1 && value > (*node)->left->value)
{
(*node)->left = leftRotate((*node)->left);
*node =rightRotate(*node);
}
// Right Left Case
if (balance < -1 && value < (*node)->right->value)
{
(*node)->right = rightRotate((*node)->right);
*node =leftRotate(*node);
}
}else if(key == (*node)->key && value == (*node)->value){
return 0;
}
return 1;
}
The code for Left Rotate is :
struct AVLTreeNode* leftRotate(struct AVLTreeNode *x){
struct AVLTreeNode *y = x->right;
struct AVLTreeNode *T2 = y->left;
// Perform rotation
y->left = x;
x->right = T2;
// Update heights
x->height = max(height(x->left), height(x->right))+1;
y->height = max(height(y->left), height(y->right))+1;
// Return new root
return y;
}
The way I am entering the values in the tree is :
int InsertNode(AVLTree *T, int k, int v)
{
//put your code here
int returnedValue = insert_in_tree_q5(&T->root, k, v);
if(returnedValue==0){
return 0;
}
return 1;
}
tree4=newAVLTree();
j=InsertNode(tree4, 10, 10);
for (i=0; i<15; i++)
{
j=InsertNode(tree4, i, i);
if (j==0) printf("(%d, %d) already exists\n", i, i);
}
The signature of the AVLTreeNode and AVLTree is:
typedef struct AVLTreeNode {
int key; //key of this item
int value; //value (int) of this item
int height; //height of the subtree rooted at this node
struct AVLTreeNode *parent; //pointer to parent
struct AVLTreeNode *left; //pointer to left child
struct AVLTreeNode *right; //pointer to right child
} AVLTreeNode;
AVLTree *newAVLTree()
{
AVLTree *T;
T = malloc(sizeof (AVLTree));
assert (T != NULL);
T->size = 0;
T->root = NULL;
return T;
}
PS: If the item (k,v) already exists, it should return 0 else add it to the tree and return 1.
Any ideas as to why it accepts all the values till (9,9) but fails at (10,10) with error "Thread 1: EXC_BAD_ACCESS (code=1, address=0x18)"
If the item (k,v) already exists, it should return 0 else add it to the tree and return 1
in insert_in_tree_q5 you do :
if(*node == NULL){
*node = newAVLTreeNode(key, value);
}
if(key != (*node)->key){
...CASE A
}
else if(key == (*node)->key){
...CASE B
} else if(key == (*node)->key && value == (*node)->value){
return 0;
}
return 1;
the case else if(key == (*node)->key && value == (*node)->value) is never reach because just before you do else if(key == (*node)->key), you need to reverse their order.
For me when (*node == NULL) you do not have to continue too
Note you already know that if(key != (*node)->key) is false so to test the equality in the two next tests is useless
Finaly your code must be :
if(*node == NULL){
*node = newAVLTreeNode(key, value);
}
else if(key != (*node)->key){
...CASE A
}
else if( value == (*node)->value){
return 0;
}
else {
...CASE B
}
return 1;
In
int InsertNode(AVLTree *T, int k, int v)
{
//put your code here
int returnedValue = insert_in_tree_q5(&T->root, k, v);
if(returnedValue==0){
return 0;
}
return 1;
}
because insert_in_tree_q5 only returns 0 or 1 InsertNode can be simplified to be just
int InsertNode(AVLTree *T, int k, int v)
{
return insert_in_tree_q5(&T->root, k, v);
}
I get a pointer with 0xCDCDCDCD when I want to print a tree but no problem when I want to print a queue in the almost same code
I write a queue by a c program and revise it to print as a tree , that queue was successful printed but when I tried to print the tree my visual studio told me there was a 0xCDCDCDCD problem.
this is the previous version that ran well.
#include<stdio.h>
#include<stdlib.h>
typedef struct _node
{
long long value;
//int value
struct _node *next;
}Node;
typedef struct _Queue
{
Node *head;
Node *tail;
}Queue;
Queue* init_queue()
{
Queue *queue=(Queue*)malloc(sizeof(Queue));
queue->head = queue->tail = NULL;
return queue;
}
void enQueue(Queue *pQueue,Node *pNode)
{
if(pQueue->head == NULL)
{//when it's empty
pQueue->head = pNode;
pQueue->tail = pNode;
}
else
{
pQueue->tail->next = pNode;
pQueue->tail = pNode;
}
}
int deQueue(Queue *pQueue)
{
int i;
if(pQueue->head == NULL)
{
return NULL;
}
// Node *deNode;
//Node *tmp;
//Node *deNode;
//deNode= pQueue->head;
Node *deNode= pQueue->head;
//Node *tmp= pQueue->head;
i=deNode->value;
pQueue->head= pQueue->head->next;
//free(deNode);
return i;
}
Node* init_node(int value)
{
Node *new_node = (Node*)malloc(sizeof(Node));
new_node->value=value;
return new_node;
}
//0:empty
int ifEmpty(Queue *pQueue)
{
if(pQueue->head == NULL)
{
printf("empty tree\n");
return 0;
}
printf("queue is not empty\n");
return 1;
}
int main()
{
Queue *queue=init_queue();
int i;
ifEmpty(queue);
printf("insert node to queue\n");
for(i=0; i<7;i++)
{
Node *node = init_node(i);
enQueue(queue,node);
// free(node);
}
// Node *node = init_node(1);
// printf("node->value = %d\n",node->value);
// enQueue(queue,node);
ifEmpty(queue);
for(i=0;i<7;i++)
{
int deNode = deQueue(queue);
//if(!deNode)
//{
//printf("NULL\n");
//}
//else
//{
printf("deNode->value = %d\n",deNode);
//}
}
//int deNode = deQueue(queue);
//free(queue);
// printf("\n after free deNode->value = %d\n",queue->head->value);
ifEmpty(queue);
return 0;
}
I want to change this into a tree format but my visual studio told me there was a 0xCDCDCDCD problem. below are my codecs:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define NUM 6
typedef struct _node
{
int value;
struct _node *left;
struct _node *right;
}TNode,*Tree;
//add a *next in q_node is my purpose
//other wise , we need to add in the Tree node struct
//So, for the sake of doesn't modify the struct of tree
//I design a q_node struct to include it
//we can use define command to make it as a template.
typedef struct _q_node
{
TNode *t_node;
int depth;
int blank; //0: means correspoinding tree node is not NULL(default)
struct _q_node *next;
}QNode;
typedef struct _Queue
{
QNode *head;
QNode *tail;
}Queue;
Queue* init_queue()
{
Queue *queue=(Queue*)malloc(sizeof(Queue));
queue->head = queue->tail = NULL;
return queue;
}
int enQueue(Queue *pQueue,TNode *pTNode,int pDepth)
{
QNode *pQNode = (QNode *)malloc(sizeof(QNode));
pQNode->depth = pDepth;
pQNode->blank = 0; //default config
if(pTNode==NULL)
{
//change default setting; 1 means it's blank QNode
pQNode->blank =1;
}
pQNode->t_node= pTNode;
if(pQueue->head == NULL)
{//when it's empty
pQueue->head = pQNode;
pQueue->tail = pQNode;
}
else
{
pQueue->tail->next = pQNode;
pQueue->tail = pQNode;
}
}
QNode* deQueue(Queue *pQueue)
{
if(pQueue->head == NULL)
{
return NULL;
}
QNode *deNode= pQueue->head;
pQueue->head = pQueue->head->next;
//pQueue->head = pQueue->head->next;
//deNode = deNode->next;
return deNode;
}
TNode* init_TNode(int value)
{
TNode *new_node = (TNode*)malloc(sizeof(TNode));
new_node->value=value;
new_node->left = new_node->right = NULL;
return new_node;
}
//0:empty
int ifEmpty(Queue *pQueue)
{
if(pQueue->head == NULL)
{
//printf("empty tree\n");
return 0;
}
//printf("queue is not empty\n");
return 1;
}
int insert_tree(Tree pTree,int pValue)
{
//found NULL sub tree, then add to his father->left
if(!pTree)
{
return 0;
}
TNode *tNode = init_TNode(pValue);
if(tNode==NULL)
{
printf("create TNode error!\n");
return 0;
}
if(pValue < pTree->value)
if(insert_tree(pTree->left,pValue)==0)
{
//no left child any more,set a new left child to pTree
pTree->left = tNode;
printf("insert :%d\n",pValue);
}
if(pValue > pTree->value)
if(insert_tree(pTree->right,pValue)==0)
{
pTree->right = tNode;
printf("insert :%d\n",pValue);
}
}
Tree creatTree(int num)
{
srand(time(NULL));
Tree root = init_TNode(rand()%100);
printf("root is %d\n",root->value);
int i ;
for(i=1;i<num;i++)
{
insert_tree(root,rand()%100);
}
printf("creat tree succuess!Tree heigh is:%d\n",get_tree_height(root));
return root ;
}
int get_tree_height(Tree pRoot)
{
if(!pRoot)
{
return 0;
}
int lh=0,rh=0;
lh = get_tree_height(pRoot->left);
rh = get_tree_height(pRoot->right);
return (lh<rh)?(rh+1):(lh+1);
}
int breath_travel(Tree pRoot,Queue *pQueue)
{
int height = get_tree_height(pRoot);
int pad_num = 3;
//compare to the node's depth in the "while loop"
int current_depth = 1;
if(!pRoot)
{
return 0;
}
enQueue(pQueue,pRoot,1);
printf("_______________________\n");
printf("breath begin,enter root:\n");
while(ifEmpty(pQueue)!=0)
{
QNode *qNode = deQueue(pQueue);
//the sub node's depth is 1 more then the parent's
int child_depth = qNode->depth + 1 ;
if(qNode->depth > current_depth)
{
current_depth = qNode->depth;
printf("\n\n");
}
// ***************0**************** pad_between = 31 ; pad_front = 15 (depth == 1)
// *******0***************0******** pad_between = 15 ; pad_front = 7 (depth == 2)
// ***0*******0*******0*******0**** pad_between = 7 ; pad_front = 3 (depth == 3)
// *0***0***0***0***0***0***0***0** pad_between = 3 ; pad_front = 1 (depth == 4)
// 0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0* pad_between = 1 ; pad_front = 0; (depth == 5)
// Tree height = 5
// pad_num = 1
// padding between node = (1+2*pad_front)*pad_num = (1+ (1<<(height-depth))-1)*pad_num
// (1<< (height - current_depth))-1=2^(height - current_depth)-1
int pad_front = (1<< (height - current_depth))-1;
if((qNode->blank == 1))
{
//add the parent node's padding:2
if(pad_front == 0) printf("%*s%*s",pad_num,"o",pad_num," ");
else printf("%*s%*s%*s",pad_front*pad_num," ",pad_num,"o",(1+pad_front)*pad_num," ");
//pad_front*pad_num+(1+pad_front)*pad_num=(1+2*pad_front)*pad_num=padding between node
if(child_depth <= height)
{
//enter two NULL sub-tree node.
//every time you enter NULL TNode,there's corresponding blank QNode.
enQueue(pQueue,NULL,child_depth);
enQueue(pQueue,NULL,child_depth);
}
}
else
{
if(pad_front == 0) printf("%*d%*s",pad_num,qNode->t_node->value,pad_num," ");
else printf("%*s%*d%*s",pad_front*pad_num," ",pad_num,qNode->t_node->value,(1+pad_front)*pad_num," ");
if(child_depth <=height)
{
enQueue(pQueue,qNode->t_node->left,child_depth);
enQueue(pQueue,qNode->t_node->right,child_depth);
}
}
} //while end
printf("\n-----------\nbreath end!\n-----------\n");
return 1;
}
int main(int argc,char **argv)
{
Queue *queue=init_queue();
int i;
ifEmpty(queue);
printf("insert node to queue\n");
int num = NUM; //default
if(argc == 2)
{
num = atoi(argv[1]);
}
Tree root = creatTree(num);
if(!root)
{
printf("create Tree failed!\n");
return 0;
}
breath_travel(root,queue);
return 0;
}
the problem is in the deQueue function when I want to print the tree my visual studio told me " pQueue->head= pQueue->head->next;" this line had a 0xCDCDCDCD
problem in the deQueue function I don't know why I even tried to put all this funtion in the main function but the problem was still there:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define NUM 6
typedef struct _node
{
int value;
struct _node *left;
struct _node *right;
}TNode, *Tree;
//add a *next in q_node is my purpose
//other wise , we need to add in the Tree node struct
//So, for the sake of doesn't modify the struct of tree
//I design a q_node struct to include it
//we can use define command to make it as a template.
typedef struct _q_node
{
TNode *t_node;
int depth;
int blank; //0: means correspoinding tree node is not NULL(default)
struct _q_node *next;
}QNode;
typedef struct _Queue
{
QNode *head;
QNode *tail;
}Queue;
Queue* init_queue()
{
Queue *queue = (Queue*)malloc(sizeof(Queue));
queue->head = queue->tail = NULL;
return queue;
}
int enQueue(Queue *pQueue, TNode *pTNode, int pDepth)
{
QNode *pQNode = (QNode *)malloc(sizeof(QNode));
pQNode->depth = pDepth;
pQNode->blank = 0; //default config
if (pTNode == NULL)
{
//change default setting; 1 means it's blank QNode
pQNode->blank = 1;
}
pQNode->t_node = pTNode;
if (pQueue->head == NULL)
{//when it's empty
pQueue->head = pQNode;
pQueue->tail = pQNode;
}
else
{
pQueue->tail->next = pQNode;
pQueue->tail = pQNode;
}
}
/*QNode* deQueue(Queue *pQueue)
{
if (pQueue->head == NULL)
{
return NULL;
}
QNode *deNode = pQueue->head;
pQueue->head = pQueue->head->next;
//pQueue->head = pQueue->head->next;
//deNode = deNode->next;
return deNode;
}
*/
TNode* init_TNode(int value)
{
TNode *new_node = (TNode*)malloc(sizeof(TNode));
new_node->value = value;
new_node->left = new_node->right = NULL;
return new_node;
}
//0:empty
int ifEmpty(Queue *pQueue)
{
if (pQueue->head == NULL)
{
//printf("empty tree\n");
return 0;
}
//printf("queue is not empty\n");
return 1;
}
int insert_tree(Tree pTree, int pValue)
{
//found NULL sub tree, then add to his father->left
if (!pTree)
{
return 0;
}
TNode *tNode = init_TNode(pValue);
if (tNode == NULL)
{
printf("create TNode error!\n");
return 0;
}
if (pValue < pTree->value)
if (insert_tree(pTree->left, pValue) == 0)
{
//no left child any more,set a new left child to pTree
pTree->left = tNode;
printf("insert :%d\n", pValue);
}
if (pValue > pTree->value)
if (insert_tree(pTree->right, pValue) == 0)
{
pTree->right = tNode;
printf("insert :%d\n", pValue);
}
}
Tree creatTree(int num)
{
srand((unsigned)time(NULL));
Tree root = init_TNode(rand() % 100);
printf("root is %d\n", root->value);
int i;
for (i = 1; i < num; i++)
{
insert_tree(root, rand() % 100);
}
printf("creat tree succuess!Tree heigh is:%d\n", get_tree_height(root));
return root;
}
int get_tree_height(Tree pRoot)
{
if (!pRoot)
{
return 0;
}
int lh = 0, rh = 0;
lh = get_tree_height(pRoot->left);
rh = get_tree_height(pRoot->right);
return (lh < rh) ? (rh + 1) : (lh + 1);
}
/*
int breath_travel(Tree pRoot, Queue *pQueue)
{
int height = get_tree_height(pRoot);
int pad_num = 3;
//compare to the node's depth in the "while loop"
int current_depth = 1;
if (!pRoot)
{
return 0;
}
enQueue(pQueue, pRoot, 1);
printf("_______________________\n");
printf("breath begin,enter root:\n");
while (ifEmpty(pQueue) != 0)
{
//QNode *qNode = deQueue(pQueue);
//the sub node's depth is 1 more then the parent's
if (pQueue->head == NULL)
{
return NULL;
}
QNode *qNode = pQueue->head;
pQueue->head = pQueue->head->next;
int child_depth = qNode->depth + 1;
if (qNode->depth > current_depth)
{
current_depth = qNode->depth;
printf("\n\n");
}
// ***************0**************** pad_between = 31 ; pad_front = 15 (depth == 1) 一共31个*
// *******0***************0******** pad_between = 15 ; pad_front = 7 (depth == 2)
// ***0*******0*******0*******0**** pad_between = 7 ; pad_front = 3 (depth == 3)
// *0***0***0***0***0***0***0***0** pad_between = 3 ; pad_front = 1 (depth == 4)
// 0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0* pad_between = 1 ; pad_front = 0; (depth == 5)
// Tree height = 5
// pad_num = 1
// padding between node = (1+2*pad_front)*pad_num = (1+ (1<<(height-depth))-1)*pad_num
// (1<< (height - current_depth))-1=2^(height - current_depth)-1
int pad_front = (1 << (height - current_depth)) - 1;
if ((qNode->blank == 1))
{
//add the parent node's padding:2
if (pad_front == 0) printf("%*s%*s", pad_num, "o", pad_num, " ");
else printf("%*s%*s%*s", pad_front*pad_num, " ", pad_num, "o", (1 + pad_front)*pad_num, " ");
//pad_front*pad_num+(1+pad_front)*pad_num=(1+2*pad_front)*pad_num=padding between node
if (child_depth <= height)
{
//enter two NULL sub-tree node.
//every time you enter NULL TNode,there's corresponding blank QNode.
enQueue(pQueue, NULL, child_depth);
enQueue(pQueue, NULL, child_depth);
}
}
else
{
if (pad_front == 0) printf("%*d%*s", pad_num, qNode->t_node->value, pad_num, " ");
else printf("%*s%*d%*s", pad_front*pad_num, " ", pad_num, qNode->t_node->value, (1 + pad_front)*pad_num, " ");
if (child_depth <= height)
{
enQueue(pQueue, qNode->t_node->left, child_depth);
enQueue(pQueue, qNode->t_node->right, child_depth);
}
}
} //while end
printf("\n-----------\nbreath end!\n-----------\n");
return 1;
}
*/
int main(int argc, char **argv)
{
Queue *pQueue = init_queue();
int i;
ifEmpty(pQueue);
printf("insert node to queue\n");
int num = NUM; //default
if (argc == 2)
{
num = atoi(argv[1]);
}
Tree pRoot = creatTree(num);
if (!pRoot)
{
printf("create Tree failed!\n");
return 0;
}
//breath_travel(root, queue);
int height = get_tree_height(pRoot);
int pad_num = 3;
//compare to the node's depth in the "while loop"
int current_depth = 1;
if (!pRoot)
{
return 0;
}
enQueue(pQueue, pRoot, 1);
printf("_______________________\n");
printf("breath begin,enter root:\n");
while (ifEmpty(pQueue) != 0)
{
//QNode *qNode = deQueue(pQueue);
//the sub node's depth is 1 more then the parent's
if (pQueue->head == NULL)
{
return NULL;
}
QNode *qNode = pQueue->head;
pQueue->head = pQueue->head->next;
int child_depth = qNode->depth + 1;
if (qNode->depth > current_depth)
{
current_depth = qNode->depth;
printf("\n\n");
}
// ***************0**************** pad_between = 31 ; pad_front = 15 (depth == 1)
// *******0***************0******** pad_between = 15 ; pad_front = 7 (depth == 2)
// ***0*******0*******0*******0**** pad_between = 7 ; pad_front = 3 (depth == 3)
// *0***0***0***0***0***0***0***0** pad_between = 3 ; pad_front = 1 (depth == 4)
// 0*0*0*0*0*0*0*0*0*0*0*0*0*0*0*0* pad_between = 1 ; pad_front = 0; (depth == 5)
// Tree height = 5
// pad_num = 1
// padding between node = (1+2*pad_front)*pad_num = (1+ (1<<(height-depth))-1)*pad_num
// (1<< (height - current_depth))-1=2^(height - current_depth)-1
int pad_front = (1 << (height - current_depth)) - 1;
if ((qNode->blank == 1))
{
//add the parent node's padding:2
if (pad_front == 0) printf("%*s%*s", pad_num, "o", pad_num, " ");
else printf("%*s%*s%*s", pad_front*pad_num, " ", pad_num, "o", (1 + pad_front)*pad_num, " ");
//pad_front*pad_num+(1+pad_front)*pad_num=(1+2*pad_front)*pad_num=padding between node
if (child_depth <= height)
{
//enter two NULL sub-tree node.
//every time you enter NULL TNode,there's corresponding blank QNode.
enQueue(pQueue, NULL, child_depth);
enQueue(pQueue, NULL, child_depth);
}
}
else
{
if (pad_front == 0) printf("%*d%*s", pad_num, qNode->t_node->value, pad_num, " ");
else printf("%*s%*d%*s", pad_front*pad_num, " ", pad_num, qNode->t_node->value, (1 + pad_front)*pad_num, " ");
if (child_depth <= height)
{
enQueue(pQueue, qNode->t_node->left, child_depth);
enQueue(pQueue, qNode->t_node->right, child_depth);
}
}
} //while end
printf("\n-----------\nbreath end!\n-----------\n");
return 0;
}
I was writing a code sample for a company I applied for, and they asked that my code run in O(n) in the worst case. I decided to use an AVL tree, but to insert the values I was being given into the AVL tree I had to use a nested loop structure. Does that make my code run in O(n2) in the worst case or does it run in O(n log n)?
EDIT: here is a link to the code on my github: https://github.com/hsleiman1/Algorithms/blob/master/equilibriumIndexAVL.c
My code:
int equilibriumIndex(int A[], int N) {
int i, newRoot = 1;
while (newRoot < N) {
node *leftTree = NULL;
node *rightTree = NULL;
for (i = 0; i < N; i++) {
if (i == newRoot) continue;
if (i < newRoot) leftTree = insert(leftTree, A[i]);
if (i >= newRoot) rightTree = insert(rightTree, A[i]);
}
if (addSubTree(leftTree) == addSubTree(rightTree)) return newRoot;
free(leftTree);
free(rightTree);
newRoot++;
}
return 0;
}
int addSubTree(node *subTree) {
if (subTree == NULL)
return 0;
else
return (subTree->value * subTree->repeat) + addSubTree(subTree->left) + addSubTree(subTree->right);
}
node *leafInit(node *leaf, int key) {
leaf = (node*)malloc(sizeof(node));
if (leaf != NULL) {
leaf->value = key;
leaf->left = NULL;
leaf->right = NULL;
leaf->repeat = 1;
}
return leaf;
}
node *insert(node *leaf, int key) {
if (leaf == NULL)
leaf = leafInit(leaf, key);
else if (key < leaf->value)
leaf->left = insert(leaf->left, key);
else
if (key > leaf->value)
leaf->right = insert(leaf->right, key);
else
leaf->repeat++;
leaf = rotate(leaf, key);
return leaf;
}
node *rotate(node *subTree, int key) {
node *temp;
int balance = getBalance(subTree);
if (balance < -1) {
temp = subTree->left;
if (key > temp->value) {
subTree->left = rightRotate(subTree->left);
subTree = leftRotate(subTree);
}
} else
if (balance > 1) {
temp = subTree->right;
if (key < temp->value) {
subTree->right = leftRotate(subTree->right);
subTree = rightRotate(subTree);
}
} else
if (balance < -1 && key < subTree->value)
subTree = leftRotate(subTree);
else
if (balance > 1 && key > subTree->value)
subTree = rightRotate(subTree);
return subTree;
}
node *leftRotate(node *leaf) {
node *x = leaf->left;
node *y = x->right;
x->right = leaf;
leaf->left = y;
return x;
}
node *rightRotate(node *leaf) {
node *x = leaf->right;
node *y = x->left;
x->left = leaf;
leaf->right = y;
return x;
}
int height(node *leaf) {
if (leaf == NULL) return 0;
else return max(height(leaf->left), height(leaf->right)) + 1;
}
int max(int num, int num1) {
if (num < num1) return num1;
else return num;
}
int getBalance(node *leaf) {
return height(leaf->right) - height(leaf->left);
}
Using an AVL tree will never get you an O(n) complexity. If you do it right, which can be tricky, you will get O(n.log(n)), and if you miss, you may get a degenerate tree and a complexity of O(n2).
For an O(n) complexity, they are expecting you to use a hash table.