Created
May 19, 2013 22:30
-
-
Save razpeitia/5609319 to your computer and use it in GitHub Desktop.
Queue and Binary Tree. Implementation.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
typedef struct node { | |
struct node *next; | |
void *data; | |
} NODE; | |
typedef struct queue { | |
NODE *back; | |
NODE *front; | |
int size; | |
void* (*allocate_node_data)(); | |
void (*free_node_data)(void *data); | |
void (*print_node_data)(void *data); | |
} QUEUE; | |
QUEUE* create_queue(void*(*allocate_node_data)(), | |
void(*free_node_datra)(void *), | |
void(*print_node_data)(void *)) { | |
QUEUE *q = (QUEUE*) malloc(sizeof(QUEUE)); | |
if(q == NULL) | |
return q; | |
q->back = NULL; | |
q->front = NULL; | |
q->size = 0; | |
q->allocate_node_data = allocate_node_data; | |
q->free_node_data = free_node_datra; | |
q->print_node_data = print_node_data; | |
return q; | |
} | |
int empty(QUEUE *q) { | |
if(q == NULL || q->front == NULL) | |
return 1; | |
return 0; | |
} | |
void enqueue(QUEUE *q, void *data) { | |
if(q == NULL) | |
return; | |
NODE *pnew = (NODE*) malloc(sizeof(NODE)); | |
if(pnew == NULL) | |
return; | |
pnew->data = data; | |
pnew->next = NULL; | |
if(q->back == NULL) | |
q->front = pnew; | |
else | |
q->back->next = pnew; | |
q->back = pnew; | |
q->size++; | |
} | |
void dequeue(QUEUE *q){ | |
if(q == NULL || q->front == NULL) | |
return; | |
NODE *p = q->front; | |
q->front = q->front->next; | |
if(q->front == NULL) | |
q->back = NULL; | |
if(q->free_node_data != NULL) | |
q->free_node_data(p->data); | |
free(p); | |
q->size--; | |
} | |
void print_queue(QUEUE *q) { | |
if(q == NULL || q->print_node_data == NULL) { | |
printf("NULL\n"); | |
return; | |
} | |
NODE *p; | |
if(q->front == NULL) | |
printf("[]\n"); | |
else{ | |
printf("["); | |
q->print_node_data(q->front->data); | |
for(p = q->front->next; p != NULL; p = p->next) { | |
printf(" "); | |
q->print_node_data(p->data); | |
} | |
printf("]\n"); | |
} | |
} | |
void* front(QUEUE *q) { | |
if(q == NULL || q->front == NULL) | |
return 0; | |
return q->front->data; | |
} | |
void* back(QUEUE *q) { | |
if(q == NULL || q->back == NULL) | |
return 0; | |
return q->back->data; | |
} | |
void destroy_queue(QUEUE **q) { | |
if( q == NULL || *q == NULL ) | |
return; | |
while( !empty(*q) ) | |
dequeue(*q); | |
free(*q); | |
*q = NULL; | |
} | |
void* allocate_() { | |
return malloc(sizeof(int)); | |
} | |
void free_(void *data) { | |
free(data); | |
} | |
void print_(void *data) { | |
printf("%d", *((int*)data)); | |
} | |
typedef struct TREE_NODE TREE_NODE; | |
typedef struct TREE_NODE { | |
TREE_NODE *left; | |
TREE_NODE *right; | |
void *data; | |
}; | |
typedef struct { | |
TREE_NODE *root; | |
int size; | |
void* (*allocate_node_data)(); | |
void (*free_node_data)(void *data); | |
void (*print_node_data)(void *data); | |
int (*compare)(void *a, void *b); | |
} TREE; | |
TREE* create_tree(void*(*allocate_node_data)(), | |
void(*free_node_data)(void *), | |
void(*print_node_data)(void *), | |
int(*compare)(void *, void *) | |
) { | |
TREE *t = (TREE*) malloc(sizeof(TREE)); | |
if(t == NULL) | |
return t; | |
t->root = NULL; | |
t->size = 0; | |
t->allocate_node_data = allocate_node_data; | |
t->free_node_data = free_node_data; | |
t->print_node_data = print_node_data; | |
t->compare = compare; | |
return t; | |
} | |
void add(TREE *t, TREE_NODE *root, TREE_NODE *p){ | |
if(t->compare(root->data, p->data) > 0) { | |
if(root->left == NULL) | |
root->left = p; | |
else | |
add(t, root->left, p); | |
} | |
else { | |
if(root->right == NULL) | |
root->right = p; | |
else | |
add(t, root->right, p); | |
} | |
} | |
void add_node(TREE *t, void *value){ | |
if(t == NULL) | |
return; | |
TREE_NODE *p = (TREE_NODE*)malloc(sizeof(TREE_NODE)); | |
if(p == NULL) | |
return; | |
p->left = NULL; | |
p->right = NULL; | |
p->data = value; | |
if(t->root == NULL) | |
t->root = p; | |
else | |
add(t, t->root, p); | |
t->size++; | |
} | |
TREE_NODE* find_node(TREE *t, TREE_NODE *root, int value) { | |
if(root == NULL) return NULL; | |
TREE_NODE *a, *b; | |
if(t->compare(root->data, &value) == 0) return root; | |
a = find_node(t, root->left, value); | |
b = find_node(t, root->right, value); | |
if(a != NULL) return a; | |
if(b != NULL) return b; | |
return NULL; | |
} | |
TREE_NODE* find(TREE *t, int value) { | |
if(t == NULL || t->root == NULL) return NULL; | |
return find_node(t, t->root, value); | |
} | |
void destroy(TREE *t, TREE_NODE *root){ | |
if(root != NULL){ | |
destroy(t, root->left); | |
destroy(t, root->right); | |
if(t->free_node_data != NULL) | |
t->free_node_data(root->data); | |
free(root); | |
} | |
} | |
void destroy_tree(TREE** t){ | |
if(t == NULL || *t == NULL) | |
return; | |
destroy(*t, (*t)->root); | |
free(*t); | |
*t = NULL; | |
} | |
int compare(void *a, void *b) { | |
if(*(int*)a == *(int*)b) | |
return 0; | |
else if(*(int*)a > *(int*)b) | |
return 1; | |
else | |
return -1; | |
} | |
void allocate_and_set(TREE *t, int value) { | |
int *p = t->allocate_node_data(); | |
*p = value; | |
add_node(t, p); | |
} | |
void set_and_enqueue(QUEUE *q, int value) { | |
int *p = q->allocate_node_data(); | |
*p = value; | |
enqueue(q, p); | |
} | |
int deep_node(TREE_NODE *root, int level) { | |
if(root == NULL) return level - 1; | |
int a, b; | |
a = deep_node(root->right, level+1); | |
b = deep_node(root->left, level+1); | |
if(a > b) | |
return a; | |
else | |
return b; | |
} | |
int deep(TREE *t) { | |
if(t == NULL || t->root == NULL) return 0; | |
return deep_node(t->root, 1); | |
} | |
void print_tree(TREE *t) { | |
if(t == NULL || t->root == NULL) return; | |
QUEUE *q = create_queue(NULL, NULL, NULL); | |
QUEUE *qlevel = create_queue(allocate_, free_, print_); | |
TREE_NODE *n; | |
int level, old_level, i; | |
enqueue(q, t->root); | |
set_and_enqueue(qlevel, 0); | |
old_level = -1; | |
while(!empty(q)) { | |
n = front(q); | |
dequeue(q); | |
level = *(int*)front(qlevel); | |
dequeue(qlevel); | |
for(i = 0; i < 2*level; i++) | |
printf(" "); | |
t->print_node_data(n->data); | |
printf(" ("); | |
if(n->left != NULL) t->print_node_data(n->left->data); | |
printf(", "); | |
if(n->right != NULL) t->print_node_data(n->right->data); | |
printf(")"); | |
printf("\n"); | |
if(n->right != NULL) { | |
enqueue(q, n->right); | |
set_and_enqueue(qlevel, level + 1); | |
} | |
if(n->left != NULL) { | |
enqueue(q, n->left); | |
set_and_enqueue(qlevel, level + 1); | |
} | |
} | |
printf("\n"); | |
destroy_queue(&q); | |
destroy_queue(&qlevel); | |
} | |
TREE_NODE* get_parent(TREE_NODE *root, TREE_NODE *n) { | |
if(root == NULL) return NULL; | |
TREE_NODE *a, *b; | |
if(root->left == n || root->right == n) return root; | |
a = get_parent(root->left, n); | |
b = get_parent(root->right, n); | |
if(a != NULL) return a; | |
if(b != NULL) return b; | |
return NULL; | |
} | |
TREE_NODE* get_successor(TREE_NODE *node) { | |
if(node->right == NULL) | |
return node; | |
return get_successor(node->right); | |
} | |
void delete_node(TREE *t, TREE_NODE *node) { | |
if(node == NULL) return; | |
TREE_NODE *parent, *successor; | |
if(node->left == NULL && node->right == NULL) { | |
parent = get_parent(t->root, node); | |
if(parent != NULL) { | |
if(parent->right == node) parent->right = NULL; | |
else parent->left = NULL; | |
} | |
t->free_node_data(node->data); | |
free(node); | |
} | |
else if(node->left == NULL && node->right != NULL) { | |
parent = get_parent(t->root, node); | |
if(parent != NULL) { | |
if(parent->right == node) parent->right = node->right; | |
else parent->left = node->right; | |
} | |
t->free_node_data(node->data); | |
free(node); | |
} | |
else if(node->left != NULL && node->right == NULL) { | |
parent = get_parent(t->root, node); | |
if(parent != NULL) { | |
if(parent->right == node) parent->right = node->left; | |
else parent->left = node->left; | |
} | |
t->free_node_data(node->data); | |
free(node); | |
} | |
else { | |
successor = get_successor(node->left); | |
t->free_node_data(node->data); | |
node->data = successor->data; | |
successor->data = NULL; | |
delete_node(t, successor); | |
} | |
} | |
int main(){ | |
TREE *t; | |
TREE_NODE *n; | |
t = create_tree(allocate_, free_, print_, compare); | |
/*allocate_and_set(t, 4); | |
allocate_and_set(t, 3); | |
allocate_and_set(t, 9); | |
allocate_and_set(t, 5); | |
allocate_and_set(t, 8); | |
allocate_and_set(t, 2); | |
allocate_and_set(t, 0); | |
allocate_and_set(t, 6); | |
allocate_and_set(t, 7); | |
allocate_and_set(t, 1);*/ | |
allocate_and_set(t, 8); | |
allocate_and_set(t, 4); | |
allocate_and_set(t, 12); | |
allocate_and_set(t, 2); | |
allocate_and_set(t, 6); | |
allocate_and_set(t, 10); | |
allocate_and_set(t, 14); | |
allocate_and_set(t, 15); | |
allocate_and_set(t, 13); | |
allocate_and_set(t, 11); | |
allocate_and_set(t, 9); | |
allocate_and_set(t, 7); | |
allocate_and_set(t, 5); | |
allocate_and_set(t, 3); | |
allocate_and_set(t, 1); | |
n = find(t, 8); | |
if(n != NULL) | |
t->print_node_data(n->data); | |
else | |
printf("Not found\n"); | |
printf("\n"); | |
print_tree(t); | |
delete_node(t, n); | |
print_tree(t); | |
printf("Tree depth: %d\n", deep(t)); | |
destroy_tree(&t); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment