Skip to content
Prev Previous commit
Next Next commit
improving tree_traversal.c
  • Loading branch information
Gathros committed May 18, 2018
commit 0cf605db475386df623862bcfea1c0d099d3437d
181 changes: 62 additions & 119 deletions chapters/tree_traversal/code/c/tree_traversal.c
Original file line number Diff line number Diff line change
@@ -1,101 +1,59 @@
#include <stdio.h>
#include "utility.h"

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

typedef struct node {
struct node {
struct node *children;
int children_num;
size_t children_size;
int id;
} node;

typedef struct node_list {
node n;
struct node_list *last_list, *next_list;
} node_list;

typedef struct node_points {
node_list *start_point, *end_point;
} node_points;

void push(node_points *np, node n) {
node_list *temp = (node_list*)malloc(sizeof(node_list));
temp->n = n;
temp->last_list = temp->next_list = NULL;

if (!np->end_point) {
np->start_point = temp;
} else {
np->end_point->next_list = temp;
temp->last_list = np->end_point;
}

np->end_point = temp;
}
};

void stack_pop(node_points *np) {
node_list *temp;
temp = np->end_point;
struct node create_tree(int rows, size_t num_children) {
struct node n = {NULL, 0, rows};

if (temp) {
np->end_point = temp->last_list;
if (!np->end_point) {
np->start_point = NULL;
if (rows > 0) {
n.children = (struct node*)malloc(num_children * sizeof(struct node));
n.children_size = num_children;
for (size_t i = 0; i < num_children; ++i) {
n.children[i] = create_tree(rows - 1, num_children);
}

free(temp);
}
}

void queue_pop(node_points *np) {
node_list *temp;
temp = np->start_point;
if (temp) {
np->start_point = temp->next_list;
if (!np->start_point) {
np->end_point = NULL;
}

free(temp);
}
return n;
}

void create_tree(node *n, int num_row, int num_child) {
n->id = num_row;
if (num_row == 0) {
n->children_num = 0;
return;
}
void destroy_tree(struct node n) {
if (n.id > 0) {
for (size_t i = 0; i < n.children_size; ++i) {
destroy_tree(n.children[i]);
}

n->children = (node *)malloc(num_child * sizeof(*n->children));
n->children_num = num_child;
for (int i = 0; i < num_child; ++i) {
node child;
create_tree(&child, num_row - 1, num_child);
*(n->children + i) = child;
free(n.children);
}
}

void dfs_recursive(node n) {
void dfs_recursive(struct node n) {
printf("%d\n", n.id);
if (!n.children) {
return;
}

for (int i = 0; i < n.children_num; ++i) {
dfs_recursive(n.children[i]);
if (n.children) {
for (size_t i = 0; i < n.children_size; ++i) {
dfs_recursive(n.children[i]);
}
}
}

void dfs_recursive_postorder(node n) {
for (int i = 0; i < n.children_num; ++i) {
void dfs_recursive_postorder(struct node n) {
for (size_t i = 0; i < n.children_size; ++i) {
dfs_recursive_postorder(n.children[i]);
}

printf("%d\n", n.id);
}

void dfs_recursive_inorder_btree(node n) {
switch (n.children_num) {
void dfs_recursive_inorder_btree(struct node n) {
switch (n.children_size) {
case 2:
dfs_recursive_inorder_btree(n.children[0]);
printf("%d\n", n.id);
Expand All @@ -114,65 +72,50 @@ void dfs_recursive_inorder_btree(node n) {
}
}

void dfs_stack(node n) {
node_points stack;
memset(&stack, 0, sizeof(node_points));
push(&stack, n);
node temp;

while (stack.start_point != NULL) {
temp = stack.end_point->n;
printf("%d\n", temp.id);
stack_pop(&stack);
for (int i = 0; i < temp.children_num; ++i) {
if (!temp.children) {
break;
}

push(&stack, temp.children[i]);
void dfs_stack(struct node n) {
struct stack stk = get_stack(sizeof(struct node*));
stack_push(&stk, &n);
struct node *tmp;

while (!stack_empty(&stk)) {
tmp = (struct node*)stack_pop(&stk);
if (!tmp) {
break;
}
}
}

void bfs_queue(node n) {
node_points queue;
memset(&queue, 0, sizeof(node_points));
push(&queue, n);
node temp;

while (queue.start_point != NULL) {
temp = queue.start_point->n;
printf("%d\n", temp.id);
queue_pop(&queue);
for (int i = 0; i < temp.children_num; ++i) {
if (!temp.children) {
break;
}

push(&queue, temp.children[i]);
printf("%d\n", tmp->id);
for (size_t i = 0; i < tmp->children_size; ++i) {
stack_push(&stk, &tmp->children[i]);
}
}

free_stack(stk);
}

void destroy_tree(node *n) {
if (n->id == 0) {
return;
}
void bfs_queue(struct node n) {
struct queue q = get_queue(sizeof(struct node*));
enqueue(&q, &n);
struct node *tmp;

for (int i = 0; i < n->children_num; ++i) {
destroy_tree(n->children + i);
while (!queue_empty(&q)) {
tmp = (struct node*)dequeue(&q);
if (!tmp) {
break;
}

printf("%d\n", tmp->id);
for (size_t i = 0; i < tmp->children_size; ++i) {
enqueue(&q, &tmp->children[i]);
}
}

free(n->children);
free_queue(q);
}

int main() {
node root;
create_tree(&root, 3, 3);
dfs_recursive(root);
//dfs_stack(root);
//bfs_queue(root);
destroy_tree(&root);
struct node root = create_tree(3, 3);
bfs_queue(root);
destroy_tree(root);

return 0;
}
105 changes: 105 additions & 0 deletions chapters/tree_traversal/code/c/utility.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#ifndef UTILITY_H
#define UTILITY_H

#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>

struct stack {
void **data;
size_t top, capacity, size;
};

struct queue {
void **data;
size_t front, back, capacity;
};

struct stack get_stack(size_t size) {
struct stack stk;

stk.data = malloc(4 * size);
stk.capacity = 4;
stk.top = 0;

return stk;
}

bool stack_empty(struct stack *stk) {
return stk->top == 0;
}

void stack_push(struct stack *stk, void *element) {
if (stk->top == stk->capacity) {
stk->capacity *= 2;
stk->data = realloc(stk->data, stk->capacity * sizeof(stk->data[0]));
}

stk->data[stk->top++] = element;
}

void *stack_pop(struct stack *stk) {
if (stack_empty(stk)) {
return NULL;
}

return stk->data[--stk->top];
}

void free_stack(struct stack stk) {
free(stk.data);
}

struct queue get_queue(size_t size) {
struct queue q;

q.data = calloc(4, size);
q.front = 0;
q.back = 0;
q.capacity = 4;

return q;
}

bool queue_empty(struct queue *q) {
return q->front == q->back;
}

void queue_resize(struct queue *q) {
size_t size = sizeof(q->data[0]);
void **tmp = calloc((q->capacity * 2), size);
memcpy(tmp, q->data + q->front, (q->capacity - q->front) * size);
memcpy(tmp + q->capacity - q->front, q->data, (q->front - 1) * size);

q->data = tmp;
q->back = q->capacity - 1;
q->front = 0;
q->capacity *= 2;
}

void enqueue(struct queue *q, void *element) {
if (q->front == (q->back % q->capacity) + 1) {
queue_resize(q);
}

q->data[q->back] = element;
q->back = (q->back + 1) % q->capacity;
}

void *dequeue(struct queue *q) {
if (queue_empty(q)) {
return NULL;
}

void *ret = q->data[q->front];
q->front = (q->front + 1) % q->capacity;

return ret;
}

void free_queue(struct queue q) {
free(q.data);
}

#endif //UTILITY_H