Skip to content

Commit

Permalink
Onto AVL trees! in ch9 of mastering algos with C
Browse files Browse the repository at this point in the history
  • Loading branch information
davidxia committed Dec 24, 2012
1 parent 81af0c5 commit e7d611e
Show file tree
Hide file tree
Showing 6 changed files with 359 additions and 0 deletions.
172 changes: 172 additions & 0 deletions algos_with_c/ch9/bitree.c
@@ -0,0 +1,172 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "bitree.h"


void bitree_init(BiTree *tree, void (*destroy)(void *data)) {
tree->size = 0;
tree->destroy = destroy;
tree->root = NULL;
return;
}


void bitree_destroy(BiTree *tree) {
/* Remove all the nodes from the tree */
bitree_rem_left(tree, NULL);
memset(tree, 0, sizeof(BiTree));
return;
}


int bitree_ins_left(BiTree *tree, BiTreeNode *node, const void *data) {
BiTreeNode *new_node, **position;

/* Determine where to insert the node */
if (node == NULL) {
/* Allow insertion at the root only in an empty tree */
if (bitree_size(tree) > 0)
return -1;
position = &tree->root;
} else {
/* Normally allow insertion only at the end of a branch */
if (bitree_left(node) != NULL)
return -1;
position = &node->left;
}

/* Allocate storage for the node */
if ((new_node = (BiTreeNode *) malloc(sizeof(BiTreeNode))) == NULL)
return -1;

/* Insert node into tree */
new_node->data = (void *) data;
new_node->left = NULL;
new_node->right = NULL;
*position = new_node;

/* Adjust the size of the tree to account for the inserted node */
tree->size++;
return 0;
}


int bitree_ins_right(BiTree *tree, BiTreeNode *node, const void *data) {
BiTreeNode *new_node, **position;

/* Determine where to insert the node */
if (node == NULL) {
/* Allow insertion at the root only in an empty tree */
if (bitree_size(tree) > 0)
return -1;
position = &tree->root;
} else {
/* Normally allow insertion only at the end of a branch */
if (bitree_right(node) != NULL)
return -1;
position = &node->right;
}

/* Allocate storage for the node */
if ((new_node = (BiTreeNode *) malloc(sizeof(BiTreeNode))) == NULL)
return -1;

/* Insert node into tree */
new_node->data = (void *) data;
new_node->left = NULL;
new_node->right = NULL;
*position = new_node;

/* Adjust the size of the tree to account for the inserted node */
tree->size++;
return 0;
}


void bitree_rem_left(BiTree *tree, BiTreeNode *node) {
BiTreeNode **position;

if (bitree_size(tree) == 0)
return;

/* Determine where to remove nodes */
if (node == NULL)
position = &tree->root;
else
position = &node->left;

/* Remove the nodes */
if (*position != NULL) {
bitree_rem_left(tree, *position);
bitree_rem_right(tree, *position);

if (tree->destroy != NULL) {
/* Call user-defined function to free dynamically allocated data */
tree->destroy((*position)->data);
}

free(*position);
*position = NULL;
tree->size--;
}

return;
}


void bitree_rem_right(BiTree *tree, BiTreeNode *node) {
BiTreeNode **position;

if (bitree_size(tree) == 0)
return;

/* Determine where to remove nodes */
if (node == NULL)
position = &tree->root;
else
position = &node->right;

/* Remove the nodes */
if (*position != NULL) {
bitree_rem_left(tree, *position);
bitree_rem_right(tree, *position);

if (tree->destroy != NULL) {
/* Call user-defined function to free dynamically allocated data */
tree->destroy((*position)->data);
}

free(*position);
*position = NULL;
tree->size--;
}

return;
}


int bitree_merge(BiTree *merge, BiTree *left, BiTree *right, const void *data) {
/* Initialize the merged tree */
bitree_init(merge, left->destroy);

if (bitree_ins_left(merge, NULL, data) != 0) {
bitree_destroy(merge);
return -1;
}

/* Merge the two binary trees into a single binary tree */
bitree_root(merge)->left = bitree_root(left);
bitree_root(merge)->right = bitree_root(right);

merge->size = merge->size + bitree_size(left) + bitree_size(right);

/* Don't left original trees access merged nodes */
left->root = NULL;
left->size = 0;
right->root = NULL;
right->size = 0;

return 0;
}

37 changes: 37 additions & 0 deletions algos_with_c/ch9/bitree.h
@@ -0,0 +1,37 @@
#ifndef BITREE_H
#define BITREE_H

#include <stdlib.h>


typedef struct BiTreeNode_ {
void *data;
struct BiTreeNode_ *left;
struct BiTreeNode_ *right;
} BiTreeNode;


typedef struct BiTree_ {
int size;
int (*compare)(const void *key1, const void *key2);
void (*destroy)(void *data);
BiTreeNode *root;
} BiTree;


void bitree_init(BiTree *tree, void (*destroy)(void *data));
void bitree_destroy(BiTree *tree);
int bitree_ins_left(BiTree *tree, BiTreeNode *node, const void *data);
int bitree_ins_right(BiTree *tree, BiTreeNode *node, const void *data);
void bitree_rem_left(BiTree *tree, BiTreeNode *node);
void bitree_rem_right(BiTree *tree, BiTreeNode *node);
int bitree_merge(BiTree *merge, BiTree *left, BiTree *right, const void *data);
#define bitree_size(tree) ((tree)->size)
#define bitree_root(tree) ((tree)->root)
#define bitree_is_eob(tree) ((node) == NULL)
#define bitree_is_leaf(tree) ((node)->left == NULL && (node)->right == NULL)
#define bitree_data(node) ((node)->data)
#define bitree_left(node) ((node)->left)
#define bitree_right(node) ((node)->right)
#endif

26 changes: 26 additions & 0 deletions algos_with_c/ch9/bitree_test.c
@@ -0,0 +1,26 @@
#include <stdio.h>
#include "bitree.h"


int main() {
BiTree tree;
BiTreeNode *node;

int data1 = 5;
int data2 = 3;
int data3 = 8;
int data4 = 1;

bitree_init(&tree, free);
bitree_ins_left(&tree, NULL, &data1);
bitree_ins_left(&tree, bitree_root(&tree), &data2);
bitree_ins_right(&tree, bitree_root(&tree), &data3);
bitree_ins_left(&tree, bitree_root(&tree)->left, &data4);

for (node = bitree_root(&tree); node != NULL; node = bitree_left(node)) {
printf("%d\n", *((int *) bitree_data(node)));
}

return 0;
}

58 changes: 58 additions & 0 deletions algos_with_c/ch9/traverse.c
@@ -0,0 +1,58 @@
#include <stdio.h>
#include "../ch5/list.h"
#include "traverse.h"


int preorder(const BiTreeNode *node, List *list) {
if (!bitree_is_eob(node)) {
if (list_ins_next(list, list_tail(list), bitree_data(node)) != 0)
return -1;

if (!bitree_is_eob(bitree_left(node)))
if (preorder(bitree_left(node), list) != 0)
return -1;

if (!bitree_is_eob(bitree_right(node)))
if (preorder(bitree_right(node), list) != 0)
return -1;
}

return 0;
}


int inorder(const BiTreeNode *node, List *list) {
if (!bitree_is_eob(node)) {
if (!bitree_is_eob(bitree_left(node)))
if (inorder(bitree_left(node), list) != 0)
return -1;

if (list_ins_next(list, list_tail(list), bitree_data(node)) != 0)
return -1;

if (!bitree_is_eob(bitree_right(node)))
if (inorder(bitree_right(node), list) != 0)
return -1;
}

return 0;
}


int postorder(const BiTreeNode *node, List *list) {
if (!bitree_is_eob(node)) {
if (!bitree_is_eob(bitree_left(node)))
if (postorder(bitree_left(node), list) != 0)
return -1;

if (!bitree_is_eob(bitree_right(node)))
if (postorder(bitree_right(node), list) != 0)
return -1;

if (list_ins_next(list, list_tail(list), bitree_data(node)) != 0)
return -1;
}

return 0;
}

4 changes: 4 additions & 0 deletions algos_with_c/ch9/traverse.h
@@ -0,0 +1,4 @@
#include "bitree.h"

int preorder(const BiTreeNode *node, List *list);
int inorder(const BiTreeNode *node, List *list);
62 changes: 62 additions & 0 deletions algos_with_c/ch9/traverse_test.c
@@ -0,0 +1,62 @@
#include <stdio.h>
#include "../ch5/list.h"
#include "traverse.h"


int main() {
BiTree tree;
List list;
ListElmt *node;

int data1 = 5;
int data2 = 3;
int data3 = 8;
int data4 = 1;
int data5 = 4;
int data6 = 2;
int data7 = 7;

bitree_init(&tree, free);
bitree_ins_left(&tree, NULL, &data1);
bitree_ins_left(&tree, bitree_root(&tree), &data2);
bitree_ins_right(&tree, bitree_root(&tree), &data3);
bitree_ins_left(&tree, bitree_root(&tree)->left, &data4);
bitree_ins_right(&tree, bitree_root(&tree)->left, &data5);
bitree_ins_left(&tree, bitree_root(&tree)->left->right, &data6);
bitree_ins_left(&tree, bitree_root(&tree)->right, &data7);

list_init(&list, NULL);
if (preorder(bitree_root(&tree), &list) != 0) {
printf("preorder traversal failed\n");
return -1;
}
printf("preorder traversal:\n");
for (node = list_head(&list); node != NULL; node = list_next(node)) {
printf("%d\n", *((int *) list_data(node)));
}

list_destroy(&list);
list_init(&list, NULL);
if (inorder(bitree_root(&tree), &list) != 0) {
printf("inorder traversal failed\n");
return -1;
}
printf("\ninorder traversal:\n");
for (node = list_head(&list); node != NULL; node = list_next(node)) {
printf("%d\n", *((int *) list_data(node)));
}

list_destroy(&list);
list_init(&list, NULL);
if (postorder(bitree_root(&tree), &list) != 0) {
printf("postorder traversal failed\n");
return -1;
}
printf("\npostorder traversal:\n");
for (node = list_head(&list); node != NULL; node = list_next(node)) {
printf("%d\n", *((int *) list_data(node)));
}

return 0;
}

0 comments on commit e7d611e

Please sign in to comment.