diff --git a/week12/AVL.c b/week12/AVL.c new file mode 100644 index 0000000..75f7a41 --- /dev/null +++ b/week12/AVL.c @@ -0,0 +1,18 @@ +#include +#include "AVL.h" + + +Node *insertNode(Node **proot, int x) { + return NULL; +} + +Node *findNode(Node *root, int x) { + return NULL; +} + +Node *deleteNode(Node **proot, int x) { + return NULL; +} + +void destroyTree(Node *root) { +} diff --git a/week12/AVL.h b/week12/AVL.h new file mode 100644 index 0000000..5c5a040 --- /dev/null +++ b/week12/AVL.h @@ -0,0 +1,42 @@ +typedef struct Node { + int key, height; + struct Node *left, *right; +} Node; + +/* function: inserts a new node to the tree + input: proot: pointer to the pointer to the tree root + x: the key of the new node + output: returns a pointer to the newly inserted node + returns NULL if insertion is not successful +*/ +Node *insertNode(Node **proot, int x); + +/* function: searches for a node in the tree + input: root: pointer to the tree root + x: the key of of the node to be searched + output: returns a pointer to the found node + returns NULL if no such node exists +*/ +Node *findNode(Node *root, int x); + +/* function: removes a node from the tree without freeing it + input: proot: pointer to the pointer to the tree root + x: the key of of the node to be deleted + output: returns a pointer to the deleted node + returns NULL if no such node exists +*/ +Node *deleteNode(Node **proot, int x); + +/* function: deletes all the nodes in the tree and frees the memory + occupied by them + input: root: pointer to the tree node + output: none +*/ +void destroyTree(Node *root); + +/* function: prints the tree in ASCII + (this function is already implemented in printTree.c) + input: root: pointer to the tree node + output: none +*/ +void printTree(Node *root); diff --git a/week12/main.c b/week12/main.c new file mode 100644 index 0000000..39dffc3 --- /dev/null +++ b/week12/main.c @@ -0,0 +1,86 @@ +#include "AVL.h" +#include +#include + +#define SIZE 16 + +int main(void) { + Node *root = NULL; + + printTree(root); + + printf("After inserting 10:\n"); + insertNode(&root, 10); + printTree(root); + + printf("\nAfter inserting 5:\n"); + insertNode(&root, 5); + printTree(root); + + printf("\nAfter inserting 15:\n"); + insertNode(&root, 15); + printTree(root); + + printf("\nAfter inserting 9, 13:\n"); + insertNode(&root, 9); + insertNode(&root, 13); + printTree(root); + + printf("\nAfter inserting 2, 6, 12 (single right rotation), 14:\n"); + insertNode(&root, 2); + insertNode(&root, 6); + insertNode(&root, 12); + insertNode(&root, 14); + printTree(root); + + printf("\nSearching for 10, 6, 13, 14, 1, 3, 11, 16:\n"); + printf(findNode(root, 10)->key == 10 ? "true\n" : "false\n"); + printf(findNode(root, 6)->key == 6 ? "true\n" : "false\n"); + printf(findNode(root, 13)->key == 13 ? "true\n" : "false\n"); + printf(findNode(root, 14)->key == 14 ? "true\n" : "false\n"); + printf(findNode(root, 1) == NULL ? "true\n" : "false\n"); + printf(findNode(root, 3) == NULL ? "true\n" : "false\n"); + printf(findNode(root, 11) == NULL ? "true\n" : "false\n"); + printf(findNode(root, 16) == NULL ? "true\n" : "false\n"); + + printf("\nAfter deleting 12 (double right left rotation):\n"); + free(deleteNode(&root, 12)); + printTree(root); + + printf("\nAfter deleting 13 (which has no children):\n"); + free(deleteNode(&root, 13)); + printTree(root); + + printf("\nAfter deleting 9 (which has a left child):\n"); + free(deleteNode(&root, 9)); + printTree(root); + + printf("\nAfter deleting 5 (which has two children):\n"); + free(deleteNode(&root, 5)); + printTree(root); + + printf("\nAfter deleting 10 (which has two children):\n"); + free(deleteNode(&root, 10)); + printTree(root); + + destroyTree(root); + + printf("\n--------------------\nSee slides 16-17, chapter 10, and slides " + "10-13, chapter 11:\n\n"); + + root = NULL; + int values[SIZE] = {3, 2, 1, 4, 5, 6, 7, 16, 15, 14, 13, 12, 11, 10, 8, 9}; + for (int i = 0; i < SIZE; i++) { + printf("inserting %d:\n", values[i]); + insertNode(&root, values[i]); + printTree(root); + printf("\n"); + } + for (int i = 0; i < SIZE; i++) { + printf("deleting %d:\n", values[i]); + deleteNode(&root, values[i]); + printTree(root); + printf("\n"); + } + return 0; +} diff --git a/week12/printTree.c b/week12/printTree.c new file mode 100644 index 0000000..4c27416 --- /dev/null +++ b/week12/printTree.c @@ -0,0 +1,248 @@ +#include "AVL.h" +#include +#include +#include + +// printing tree in ascii + +typedef struct asciinode_struct asciinode; + +struct asciinode_struct { + asciinode *left, *right; + + // length of the edge from this node to its children + int edge_length; + + int height; + + int lablen; + + //-1=I am left, 0=I am root, 1=right + int parent_dir; + + // max supported unit32 in dec, 10 digits max + char label[11]; +}; + +#define MAX_HEIGHT 1000 +int lprofile[MAX_HEIGHT]; +int rprofile[MAX_HEIGHT]; +#define INFINITY (1 << 20) + +// adjust gap between left and right nodes +int gap = 3; + +// used for printing next node in the same level, +// this is the x coordinate of the next char printed +int print_next; + +int MIN(int X, int Y) { return ((X) < (Y)) ? (X) : (Y); } + +int MAX(int X, int Y) { return ((X) > (Y)) ? (X) : (Y); } + +asciinode *build_ascii_tree_recursive(Node *t) { + asciinode *node; + + if (t == NULL) + return NULL; + + node = (asciinode *)malloc(sizeof(asciinode)); + node->left = build_ascii_tree_recursive(t->left); + node->right = build_ascii_tree_recursive(t->right); + + if (node->left != NULL) { + node->left->parent_dir = -1; + } + + if (node->right != NULL) { + node->right->parent_dir = 1; + } + + sprintf(node->label, "%d|%d", t->key, t->height); + + node->lablen = strlen(node->label); + + return node; +} + +// Copy the tree into the ascii node structre +asciinode *build_ascii_tree(Node *t) { + asciinode *node; + if (t == NULL) + return NULL; + node = build_ascii_tree_recursive(t); + node->parent_dir = 0; + return node; +} + +// Free all the nodes of the given tree +void free_ascii_tree(asciinode *node) { + if (node == NULL) + return; + free_ascii_tree(node->left); + free_ascii_tree(node->right); + free(node); +} + +// The following function fills in the lprofile array for the given tree. +// It assumes that the center of the label of the root of this tree +// is located at a position (x,y). It assumes that the edge_length +// fields have been computed for this tree. +void compute_lprofile(asciinode *node, int x, int y) { + int i, isleft; + if (node == NULL) + return; + isleft = (node->parent_dir == -1); + lprofile[y] = MIN(lprofile[y], x - ((node->lablen - isleft) / 2)); + if (node->left != NULL) { + for (i = 1; i <= node->edge_length && y + i < MAX_HEIGHT; i++) { + lprofile[y + i] = MIN(lprofile[y + i], x - i); + } + } + compute_lprofile(node->left, x - node->edge_length - 1, + y + node->edge_length + 1); + compute_lprofile(node->right, x + node->edge_length + 1, + y + node->edge_length + 1); +} + +void compute_rprofile(asciinode *node, int x, int y) { + int i, notleft; + if (node == NULL) + return; + notleft = (node->parent_dir != -1); + rprofile[y] = MAX(rprofile[y], x + ((node->lablen - notleft) / 2)); + if (node->right != NULL) { + for (i = 1; i <= node->edge_length && y + i < MAX_HEIGHT; i++) { + rprofile[y + i] = MAX(rprofile[y + i], x + i); + } + } + compute_rprofile(node->left, x - node->edge_length - 1, + y + node->edge_length + 1); + compute_rprofile(node->right, x + node->edge_length + 1, + y + node->edge_length + 1); +} + +// This function fills in the edge_length and +// height fields of the specified tree +void compute_edge_lengths(asciinode *node) { + int h, hmin, i, delta; + if (node == NULL) + return; + compute_edge_lengths(node->left); + compute_edge_lengths(node->right); + + /* first fill in the edge_length of node */ + if (node->right == NULL && node->left == NULL) { + node->edge_length = 0; + } else { + if (node->left != NULL) { + for (i = 0; i < node->left->height && i < MAX_HEIGHT; i++) { + rprofile[i] = -INFINITY; + } + compute_rprofile(node->left, 0, 0); + hmin = node->left->height; + } else { + hmin = 0; + } + if (node->right != NULL) { + for (i = 0; i < node->right->height && i < MAX_HEIGHT; i++) { + lprofile[i] = INFINITY; + } + compute_lprofile(node->right, 0, 0); + hmin = MIN(node->right->height, hmin); + } else { + hmin = 0; + } + delta = 4; + for (i = 0; i < hmin; i++) { + delta = MAX(delta, gap + 1 + rprofile[i] - lprofile[i]); + } + + // If the node has two children of height 1, then we allow the + // two leaves to be within 1, instead of 2 + if (((node->left != NULL && node->left->height == 1) || + (node->right != NULL && node->right->height == 1)) && + delta > 4) { + delta--; + } + + node->edge_length = ((delta + 1) / 2) - 1; + } + + // now fill in the height of node + h = 1; + if (node->left != NULL) { + h = MAX(node->left->height + node->edge_length + 1, h); + } + if (node->right != NULL) { + h = MAX(node->right->height + node->edge_length + 1, h); + } + node->height = h; +} + +// This function prints the given level of the given tree, assuming +// that the node has the given x cordinate. +void print_level(asciinode *node, int x, int level) { + int i, isleft; + if (node == NULL) + return; + isleft = (node->parent_dir == -1); + if (level == 0) { + for (i = 0; i < (x - print_next - ((node->lablen - isleft) / 2)); i++) { + printf(" "); + } + print_next += i; + printf("%s", node->label); + print_next += node->lablen; + } else if (node->edge_length >= level) { + if (node->left != NULL) { + for (i = 0; i < (x - print_next - (level)); i++) { + printf(" "); + } + print_next += i; + printf("/"); + print_next++; + } + if (node->right != NULL) { + for (i = 0; i < (x - print_next + (level)); i++) { + printf(" "); + } + print_next += i; + printf("\\"); + print_next++; + } + } else { + print_level(node->left, x - node->edge_length - 1, + level - node->edge_length - 1); + print_level(node->right, x + node->edge_length + 1, + level - node->edge_length - 1); + } +} + +// prints ascii tree for given Node structure +void printTree(Node *root) { + asciinode *proot; + int xmin, i; + if (root == NULL) + return; + proot = build_ascii_tree(root); + compute_edge_lengths(proot); + for (i = 0; i < proot->height && i < MAX_HEIGHT; i++) { + lprofile[i] = INFINITY; + } + compute_lprofile(proot, 0, 0); + xmin = 0; + for (i = 0; i < proot->height && i < MAX_HEIGHT; i++) { + xmin = MIN(xmin, lprofile[i]); + } + for (i = 0; i < proot->height; i++) { + print_next = 0; + print_level(proot, -xmin, i); + printf("\n"); + } + if (proot->height >= MAX_HEIGHT) { + printf("(This tree is taller than %d, and may be drawn incorrectly.)\n", + MAX_HEIGHT); + } + free_ascii_tree(proot); +}