week13 format mowgli AVL

This commit is contained in:
2021-05-26 20:20:01 +08:00
parent 679b38ab78
commit cacf5445ad
4 changed files with 424 additions and 512 deletions

View File

@@ -1,21 +1,18 @@
#include <stdio.h>
#include "AVL.h" #include "AVL.h"
#include <malloc.h> #include <malloc.h>
#include <math.h> #include <math.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
int max(int a, int b) int max(int a, int b) {
{ if (a > b) {
if (a > b)
{
return a; return a;
} }
return b; return b;
} }
int getHeight(Node *N) int getHeight(Node *N) {
{
if (N == NULL) if (N == NULL)
return -1; return -1;
@@ -28,33 +25,25 @@ int getHeight(Node *N)
return y + 1; return y + 1;
} }
int getBalance(Node *N) int getBalance(Node *N) { return getHeight(N->left) - getHeight(N->right); }
{
return getHeight(N->left) - getHeight(N->right);
}
Node *findNode(Node *root, int x) Node *findNode(Node *root, int x) {
{ if (root == NULL) {
if (root == NULL)
{
return NULL; return NULL;
} }
if (root->key == x) if (root->key == x) {
{
return root; return root;
} }
if (x < root->key) if (x < root->key) {
{
return findNode(root->left, x); return findNode(root->left, x);
} }
return findNode(root->right, x); return findNode(root->right, x);
} }
Node *rightRotate(Node *N) Node *rightRotate(Node *N) {
{
Node *N1 = N->left; Node *N1 = N->left;
Node *N2 = N1->right; Node *N2 = N1->right;
@@ -67,8 +56,7 @@ Node *rightRotate(Node *N)
return N1; return N1;
} }
Node *leftRotate(Node *N) Node *leftRotate(Node *N) {
{
Node *N1 = N->right; Node *N1 = N->right;
Node *N2 = N1->left; Node *N2 = N1->left;
@@ -81,22 +69,18 @@ Node *leftRotate(Node *N)
return N1; return N1;
} }
Node *minNode(Node *N) Node *minNode(Node *N) {
{ while (N->left != NULL) {
while (N->left != NULL)
{
N = N->left; N = N->left;
} }
return N; return N;
} }
Node *insertNode(Node **root, int x) Node *insertNode(Node **root, int x) {
{
Node *ans; Node *ans;
/* insert the data */ /* insert the data */
if (*root == NULL) if (*root == NULL) {
{
Node *temp = (Node *)malloc(sizeof(Node)); Node *temp = (Node *)malloc(sizeof(Node));
temp->key = x; temp->key = x;
temp->height = 0; temp->height = 0;
@@ -105,93 +89,75 @@ Node *insertNode(Node **root, int x)
*root = temp; *root = temp;
ans = temp; ans = temp;
return ans; return ans;
} } else if ((*root)->key > x) {
else if ((*root)->key > x)
{
ans = insertNode(&(*root)->left, x); ans = insertNode(&(*root)->left, x);
} } else if ((*root)->key < x) {
else if ((*root)->key < x)
{
ans = insertNode(&(*root)->right, x); ans = insertNode(&(*root)->right, x);
} }
/* handle the unbalance problem */ /* handle the unbalance problem */
(*root)->height = 1 + max(getHeight((*root)->left), getHeight((*root)->right)); (*root)->height =
1 + max(getHeight((*root)->left), getHeight((*root)->right));
int balance = getBalance(*root); int balance = getBalance(*root);
/* case 1 left left unbalance */ /* case 1 left left unbalance */
if (balance > 1 && getBalance((*root)->left) >= 0) if (balance > 1 && getBalance((*root)->left) >= 0) {
{
*root = rightRotate(*root); *root = rightRotate(*root);
} }
/* case 2 left right unbalance */ /* case 2 left right unbalance */
if (balance > 1 && getBalance((*root)->left) < 0) if (balance > 1 && getBalance((*root)->left) < 0) {
{
(*root)->left = leftRotate((*root)->left); (*root)->left = leftRotate((*root)->left);
*root = rightRotate(*root); *root = rightRotate(*root);
} }
/* case 3 right left unbalance */ /* case 3 right left unbalance */
if (balance < -1 && getBalance((*root)->right) > 0) if (balance < -1 && getBalance((*root)->right) > 0) {
{
(*root)->right = rightRotate((*root)->right); (*root)->right = rightRotate((*root)->right);
*root = leftRotate(*root); *root = leftRotate(*root);
} }
/* case 4 right right unbalance */ /* case 4 right right unbalance */
if (balance < -1 && getBalance((*root)->right) <= 0) if (balance < -1 && getBalance((*root)->right) <= 0) {
{
*root = leftRotate(*root); *root = leftRotate(*root);
} }
return ans; return ans;
} }
Node *deleteNode(Node **root, int x) Node *deleteNode(Node **root, int x) {
{
Node *temp = *root; Node *temp = *root;
if (*root == NULL) if (*root == NULL)
return *root; return *root;
if (x < (*root)->key) if (x < (*root)->key) {
{
temp = deleteNode(&(*root)->left, x); temp = deleteNode(&(*root)->left, x);
} }
else if (x > (*root)->key) else if (x > (*root)->key) {
{
temp = deleteNode(&(*root)->right, x); temp = deleteNode(&(*root)->right, x);
} }
else else {
{ if ((*root)->left == NULL || (*root)->right == NULL) {
if ((*root)->left == NULL || (*root)->right == NULL)
{
Node *child = (*root)->left != NULL ? (*root)->left : (*root)->right; Node *child = (*root)->left != NULL ? (*root)->left : (*root)->right;
if (child == NULL) if (child == NULL) { // no child case;
{ // no child case;
*root = NULL; *root = NULL;
return temp; return temp;
} } else {
else
{
(*root)->key = child->key; (*root)->key = child->key;
if ((*root)->left && (*root)->left->key == child->key) if ((*root)->left &&
{ // left child case; (*root)->left->key == child->key) { // left child case;
temp = deleteNode(&(*root)->left, child->key); temp = deleteNode(&(*root)->left, child->key);
} } else if ((*root)->right &&
else if ((*root)->right && (*root)->right->key == child->key) (*root)->right->key == child->key) { // right child case;
{ // right child case;
temp = deleteNode(&(*root)->right, child->key); temp = deleteNode(&(*root)->right, child->key);
} }
} }
} } else { // two children case;
else
{ // two children case;
Node *child = minNode((*root)->right); Node *child = minNode((*root)->right);
(*root)->key = child->key; (*root)->key = child->key;
temp = deleteNode(&(*root)->right, child->key); temp = deleteNode(&(*root)->right, child->key);
@@ -203,39 +169,35 @@ Node *deleteNode(Node **root, int x)
int balance = getBalance(*root); int balance = getBalance(*root);
(*root)->height = 1 + max(getHeight((*root)->left), getHeight((*root)->right)); (*root)->height =
1 + max(getHeight((*root)->left), getHeight((*root)->right));
/* case 1 left left unbalance */ /* case 1 left left unbalance */
if (balance > 1 && getBalance((*root)->left) >= 0) if (balance > 1 && getBalance((*root)->left) >= 0) {
{
*root = rightRotate(*root); *root = rightRotate(*root);
} }
/* case 2 left right unbalance */ /* case 2 left right unbalance */
if (balance > 1 && getBalance((*root)->left) < 0) if (balance > 1 && getBalance((*root)->left) < 0) {
{
(*root)->left = leftRotate((*root)->left); (*root)->left = leftRotate((*root)->left);
*root = rightRotate(*root); *root = rightRotate(*root);
} }
/* case 3 right left unbalance */ /* case 3 right left unbalance */
if (balance < -1 && getBalance((*root)->right) > 0) if (balance < -1 && getBalance((*root)->right) > 0) {
{
(*root)->right = rightRotate((*root)->right); (*root)->right = rightRotate((*root)->right);
*root = leftRotate(*root); *root = leftRotate(*root);
} }
/* case 4 right right unbalance */ /* case 4 right right unbalance */
if (balance < -1 && getBalance((*root)->right) <= 0) if (balance < -1 && getBalance((*root)->right) <= 0) {
{
*root = leftRotate(*root); *root = leftRotate(*root);
} }
return temp; return temp;
} }
void destroyTree(Node *root) void destroyTree(Node *root) {
{
if (root == NULL) if (root == NULL)
return; return;

View File

@@ -1,6 +1,5 @@
typedef struct Node Node; typedef struct Node Node;
typedef struct Node typedef struct Node {
{
int key, height; int key, height;
Node *left, *right; Node *left, *right;
} Node; } Node;

View File

@@ -1,23 +1,21 @@
#include "AVL.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "AVL.h"
int main() int main() {
{
Node *root = NULL; Node *root = NULL;
int ins[] = {16, 10, 21, 5, 12, 18, 24, 2, 8, 11, 15, 19, 23, 31, 1, 6, 9, 13, 22, 7}; int ins[] = {16, 10, 21, 5, 12, 18, 24, 2, 8, 11,
15, 19, 23, 31, 1, 6, 9, 13, 22, 7};
int len = 20, x; int len = 20, x;
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++) {
{
printf("\nAfter inserting key %d..\n", ins[i]); printf("\nAfter inserting key %d..\n", ins[i]);
insertNode(&root, ins[i]); insertNode(&root, ins[i]);
printTree(root); printTree(root);
} }
printf("\nInsert a new node (+ to insert, - to delete, 0 to exit): "); printf("\nInsert a new node (+ to insert, - to delete, 0 to exit): ");
scanf("%d", &x); scanf("%d", &x);
while (x) while (x) {
{
if (x > 0) if (x > 0)
insertNode(&root, x); insertNode(&root, x);
else else

View File

@@ -1,14 +1,13 @@
#include "AVL.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "AVL.h"
// printing tree in ascii // printing tree in ascii
typedef struct asciinode_struct asciinode; typedef struct asciinode_struct asciinode;
struct asciinode_struct struct asciinode_struct {
{
asciinode *left, *right; asciinode *left, *right;
// length of the edge from this node to its children // length of the edge from this node to its children
@@ -37,18 +36,11 @@ int gap = 3;
// this is the x coordinate of the next char printed // this is the x coordinate of the next char printed
int print_next; int print_next;
int MIN(int X, int Y) int MIN(int X, int Y) { return ((X) < (Y)) ? (X) : (Y); }
{
return ((X) < (Y)) ? (X) : (Y);
}
int MAX(int X, int Y) int MAX(int X, int Y) { return ((X) > (Y)) ? (X) : (Y); }
{
return ((X) > (Y)) ? (X) : (Y);
}
asciinode *build_ascii_tree_recursive(Node *t) asciinode *build_ascii_tree_recursive(Node *t) {
{
asciinode *node; asciinode *node;
if (t == NULL) if (t == NULL)
@@ -58,13 +50,11 @@ asciinode *build_ascii_tree_recursive(Node *t)
node->left = build_ascii_tree_recursive(t->left); node->left = build_ascii_tree_recursive(t->left);
node->right = build_ascii_tree_recursive(t->right); node->right = build_ascii_tree_recursive(t->right);
if (node->left != NULL) if (node->left != NULL) {
{
node->left->parent_dir = -1; node->left->parent_dir = -1;
} }
if (node->right != NULL) if (node->right != NULL) {
{
node->right->parent_dir = 1; node->right->parent_dir = 1;
} }
@@ -76,8 +66,7 @@ asciinode *build_ascii_tree_recursive(Node *t)
} }
// Copy the tree into the ascii node structre // Copy the tree into the ascii node structre
asciinode *build_ascii_tree(Node *t) asciinode *build_ascii_tree(Node *t) {
{
asciinode *node; asciinode *node;
if (t == NULL) if (t == NULL)
return NULL; return NULL;
@@ -87,8 +76,7 @@ asciinode *build_ascii_tree(Node *t)
} }
// Free all the nodes of the given tree // Free all the nodes of the given tree
void free_ascii_tree(asciinode *node) void free_ascii_tree(asciinode *node) {
{
if (node == NULL) if (node == NULL)
return; return;
free_ascii_tree(node->left); free_ascii_tree(node->left);
@@ -100,46 +88,43 @@ void free_ascii_tree(asciinode *node)
// It assumes that the center of the label of the root of this 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 // is located at a position (x,y). It assumes that the edge_length
// fields have been computed for this tree. // fields have been computed for this tree.
void compute_lprofile(asciinode *node, int x, int y) void compute_lprofile(asciinode *node, int x, int y) {
{
int i, isleft; int i, isleft;
if (node == NULL) if (node == NULL)
return; return;
isleft = (node->parent_dir == -1); isleft = (node->parent_dir == -1);
lprofile[y] = MIN(lprofile[y], x - ((node->lablen - isleft) / 2)); lprofile[y] = MIN(lprofile[y], x - ((node->lablen - isleft) / 2));
if (node->left != NULL) if (node->left != NULL) {
{ for (i = 1; i <= node->edge_length && y + i < MAX_HEIGHT; i++) {
for (i = 1; i <= node->edge_length && y + i < MAX_HEIGHT; i++)
{
lprofile[y + i] = MIN(lprofile[y + i], x - 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->left, x - node->edge_length - 1,
compute_lprofile(node->right, x + node->edge_length + 1, y + 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) void compute_rprofile(asciinode *node, int x, int y) {
{
int i, notleft; int i, notleft;
if (node == NULL) if (node == NULL)
return; return;
notleft = (node->parent_dir != -1); notleft = (node->parent_dir != -1);
rprofile[y] = MAX(rprofile[y], x + ((node->lablen - notleft) / 2)); rprofile[y] = MAX(rprofile[y], x + ((node->lablen - notleft) / 2));
if (node->right != NULL) if (node->right != NULL) {
{ for (i = 1; i <= node->edge_length && y + i < MAX_HEIGHT; i++) {
for (i = 1; i <= node->edge_length && y + i < MAX_HEIGHT; i++)
{
rprofile[y + i] = MAX(rprofile[y + i], x + 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->left, x - node->edge_length - 1,
compute_rprofile(node->right, x + node->edge_length + 1, y + 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 // This function fills in the edge_length and
// height fields of the specified tree // height fields of the specified tree
void compute_edge_lengths(asciinode *node) void compute_edge_lengths(asciinode *node) {
{
int h, hmin, i, delta; int h, hmin, i, delta;
if (node == NULL) if (node == NULL)
return; return;
@@ -147,41 +132,29 @@ void compute_edge_lengths(asciinode *node)
compute_edge_lengths(node->right); compute_edge_lengths(node->right);
/* first fill in the edge_length of node */ /* first fill in the edge_length of node */
if (node->right == NULL && node->left == NULL) if (node->right == NULL && node->left == NULL) {
{
node->edge_length = 0; node->edge_length = 0;
} } else {
else if (node->left != NULL) {
{ for (i = 0; i < node->left->height && i < MAX_HEIGHT; i++) {
if (node->left != NULL)
{
for (i = 0; i < node->left->height && i < MAX_HEIGHT; i++)
{
rprofile[i] = -INFINITY; rprofile[i] = -INFINITY;
} }
compute_rprofile(node->left, 0, 0); compute_rprofile(node->left, 0, 0);
hmin = node->left->height; hmin = node->left->height;
} } else {
else
{
hmin = 0; hmin = 0;
} }
if (node->right != NULL) if (node->right != NULL) {
{ for (i = 0; i < node->right->height && i < MAX_HEIGHT; i++) {
for (i = 0; i < node->right->height && i < MAX_HEIGHT; i++)
{
lprofile[i] = INFINITY; lprofile[i] = INFINITY;
} }
compute_lprofile(node->right, 0, 0); compute_lprofile(node->right, 0, 0);
hmin = MIN(node->right->height, hmin); hmin = MIN(node->right->height, hmin);
} } else {
else
{
hmin = 0; hmin = 0;
} }
delta = 4; delta = 4;
for (i = 0; i < hmin; i++) for (i = 0; i < hmin; i++) {
{
delta = MAX(delta, gap + 1 + rprofile[i] - lprofile[i]); delta = MAX(delta, gap + 1 + rprofile[i] - lprofile[i]);
} }
@@ -189,8 +162,7 @@ void compute_edge_lengths(asciinode *node)
// two leaves to be within 1, instead of 2 // two leaves to be within 1, instead of 2
if (((node->left != NULL && node->left->height == 1) || if (((node->left != NULL && node->left->height == 1) ||
(node->right != NULL && node->right->height == 1)) && (node->right != NULL && node->right->height == 1)) &&
delta > 4) delta > 4) {
{
delta--; delta--;
} }
@@ -199,12 +171,10 @@ void compute_edge_lengths(asciinode *node)
// now fill in the height of node // now fill in the height of node
h = 1; h = 1;
if (node->left != NULL) if (node->left != NULL) {
{
h = MAX(node->left->height + node->edge_length + 1, h); h = MAX(node->left->height + node->edge_length + 1, h);
} }
if (node->right != NULL) if (node->right != NULL) {
{
h = MAX(node->right->height + node->edge_length + 1, h); h = MAX(node->right->height + node->edge_length + 1, h);
} }
node->height = h; node->height = h;
@@ -212,84 +182,67 @@ void compute_edge_lengths(asciinode *node)
// This function prints the given level of the given tree, assuming // This function prints the given level of the given tree, assuming
// that the node has the given x cordinate. // that the node has the given x cordinate.
void print_level(asciinode *node, int x, int level) void print_level(asciinode *node, int x, int level) {
{
int i, isleft; int i, isleft;
if (node == NULL) if (node == NULL)
return; return;
isleft = (node->parent_dir == -1); isleft = (node->parent_dir == -1);
if (level == 0) if (level == 0) {
{ for (i = 0; i < (x - print_next - ((node->lablen - isleft) / 2)); i++) {
for (i = 0; i < (x - print_next - ((node->lablen - isleft) / 2)); i++)
{
printf(" "); printf(" ");
} }
print_next += i; print_next += i;
printf("%s", node->label); printf("%s", node->label);
print_next += node->lablen; print_next += node->lablen;
} } else if (node->edge_length >= level) {
else if (node->edge_length >= level) if (node->left != NULL) {
{ for (i = 0; i < (x - print_next - (level)); i++) {
if (node->left != NULL)
{
for (i = 0; i < (x - print_next - (level)); i++)
{
printf(" "); printf(" ");
} }
print_next += i; print_next += i;
printf("/"); printf("/");
print_next++; print_next++;
} }
if (node->right != NULL) if (node->right != NULL) {
{ for (i = 0; i < (x - print_next + (level)); i++) {
for (i = 0; i < (x - print_next + (level)); i++)
{
printf(" "); printf(" ");
} }
print_next += i; print_next += i;
printf("\\"); printf("\\");
print_next++; print_next++;
} }
} } else {
else print_level(node->left, x - node->edge_length - 1,
{
print_level(node->left,
x - node->edge_length - 1,
level - node->edge_length - 1); level - node->edge_length - 1);
print_level(node->right, print_level(node->right, x + node->edge_length + 1,
x + node->edge_length + 1,
level - node->edge_length - 1); level - node->edge_length - 1);
} }
} }
// prints ascii tree for given Node structure // prints ascii tree for given Node structure
void printTree(Node *root) void printTree(Node *root) {
{
asciinode *proot; asciinode *proot;
int xmin, i; int xmin, i;
if (root == NULL) if (root == NULL)
return; return;
proot = build_ascii_tree(root); proot = build_ascii_tree(root);
compute_edge_lengths(proot); compute_edge_lengths(proot);
for (i = 0; i < proot->height && i < MAX_HEIGHT; i++) for (i = 0; i < proot->height && i < MAX_HEIGHT; i++) {
{
lprofile[i] = INFINITY; lprofile[i] = INFINITY;
} }
compute_lprofile(proot, 0, 0); compute_lprofile(proot, 0, 0);
xmin = 0; xmin = 0;
for (i = 0; i < proot->height && i < MAX_HEIGHT; i++) for (i = 0; i < proot->height && i < MAX_HEIGHT; i++) {
{
xmin = MIN(xmin, lprofile[i]); xmin = MIN(xmin, lprofile[i]);
} }
for (i = 0; i < proot->height; i++) for (i = 0; i < proot->height; i++) {
{
print_next = 0; print_next = 0;
print_level(proot, -xmin, i); print_level(proot, -xmin, i);
printf("\n"); printf("\n");
} }
if (proot->height >= MAX_HEIGHT) if (proot->height >= MAX_HEIGHT) {
{ printf("(This tree is taller than %d, and may be drawn incorrectly.)\n",
printf("(This tree is taller than %d, and may be drawn incorrectly.)\n", MAX_HEIGHT); MAX_HEIGHT);
} }
free_ascii_tree(proot); free_ascii_tree(proot);
} }