week10 BST
This commit is contained in:
103
week10/BST.c
Normal file
103
week10/BST.c
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Author: Walter
|
||||||
|
* Student ID: 1930006025
|
||||||
|
* week_10_BST
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BST.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
Node *insertNode(Node **proot, int x) {
|
||||||
|
/* create if empty */
|
||||||
|
if ((*proot) == NULL) {
|
||||||
|
*proot = (Node *)malloc(sizeof(Node));
|
||||||
|
if (*proot == NULL) {
|
||||||
|
fprintf(stderr, "Can not allocate new space for node\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
(*proot)->key = x;
|
||||||
|
(*proot)->left = (*proot)->right = NULL;
|
||||||
|
return *proot;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x < (*proot)->key) {
|
||||||
|
return insertNode(&((*proot)->left), x);
|
||||||
|
} else if (x > (*proot)->key) {
|
||||||
|
return insertNode(&((*proot)->right), x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* equal, do nothing and return NULL,
|
||||||
|
* because insertion is not successful */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *findNode(Node *root, int x) {
|
||||||
|
/* empty tree */
|
||||||
|
if (root == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x < root->key) {
|
||||||
|
return findNode(root->left, x);
|
||||||
|
} else if (x > root->key) {
|
||||||
|
return findNode(root->right, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* equal */
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *deleteNode(Node **proot, int x) {
|
||||||
|
Node *tmpNode;
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
if (*proot == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the node needs to be delete */
|
||||||
|
if (x < (*proot)->key) {
|
||||||
|
return deleteNode(&((*proot)->left), x);
|
||||||
|
} else if (x > (*proot)->key) {
|
||||||
|
return deleteNode(&((*proot)->right), x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*proot)->left && (*proot)->right) {
|
||||||
|
/* two child, find the min on right to replace */
|
||||||
|
tmpNode = (*proot)->right;
|
||||||
|
while (tmpNode->left) {
|
||||||
|
tmpNode = tmpNode->left;
|
||||||
|
}
|
||||||
|
/* simply replace key value */
|
||||||
|
(*proot)->key = tmpNode->key;
|
||||||
|
/* delete tmpNode, which has one or zero child */
|
||||||
|
return deleteNode(&(*proot)->right, tmpNode->key);
|
||||||
|
} else if ((*proot)->left || (*proot)->right) {
|
||||||
|
/* one child */
|
||||||
|
tmpNode = *proot;
|
||||||
|
if ((*proot)->left) {
|
||||||
|
*proot = (*proot)->left;
|
||||||
|
}
|
||||||
|
if ((*proot)->right) {
|
||||||
|
*proot = (*proot)->right;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* no child */
|
||||||
|
tmpNode = *proot;
|
||||||
|
*proot = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmpNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroyTree(Node *root) {
|
||||||
|
/* end situation */
|
||||||
|
if (root == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
destroyTree(root->left);
|
||||||
|
destroyTree(root->right);
|
||||||
|
free(root);
|
||||||
|
return;
|
||||||
|
}
|
||||||
42
week10/BST.h
Normal file
42
week10/BST.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
typedef struct Node {
|
||||||
|
int key;
|
||||||
|
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);
|
||||||
66
week10/main.c
Normal file
66
week10/main.c
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#include "BST.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
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, 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 (which has no children):\n");
|
||||||
|
free(deleteNode(&root, 12));
|
||||||
|
printTree(root);
|
||||||
|
|
||||||
|
printf("\nAfter deleting 13 (which has a right child):\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);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
248
week10/printTree.c
Normal file
248
week10/printTree.c
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
#include "BST.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// 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", t->key);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user