From db894676f76ab55847f1fc007b62c8dd78d1d74a Mon Sep 17 00:00:00 2001 From: heimoshuiyu Date: Wed, 26 May 2021 21:45:27 +0800 Subject: [PATCH] week12 AVL (from mowgli) --- week12/AVL.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 209 insertions(+), 18 deletions(-) diff --git a/week12/AVL.c b/week12/AVL.c index 75f7a41..10dd394 100644 --- a/week12/AVL.c +++ b/week12/AVL.c @@ -1,18 +1,209 @@ -#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) { -} +#include "AVL.h" +#include +#include +#include +#include + +int max(int a, int b) { + if (a > b) { + return a; + } + return b; +} + +int getHeight(Node *node) { + int x, y; + + if (node == NULL) { + return -1; + } + + x = getHeight(node->left); + y = getHeight(node->right); + + return x >= y ? x + 1 : y + 1; +} + +int getBalance(Node *node) { + return getHeight(node->left) - getHeight(node->right); +} + +Node *findNode(Node *root, int x) { + if (root == NULL) { + return NULL; + } + + if (root->key == x) { + return root; + } + + return x < root->key ? findNode(root->left, x) : findNode(root->right, x); +} + +Node *rightRotate(Node *node) { + Node *left = node->left; + Node *right = left->right; + + left->right = node; + node->left = right; + + node->height = max(getHeight(node->left), getHeight(node->right)) + 1; + left->height = max(getHeight(left->left), getHeight(left->right)) + 1; + + return left; +} + +Node *leftRotate(Node *node) { + Node *right = node->right; + Node *left = right->left; + + right->left = node; + node->right = left; + + node->height = max(getHeight(node->left), getHeight(node->right)) + 1; + right->height = max(getHeight(right->left), getHeight(right->right)) + 1; + + return right; +} + +Node *minNode(Node *node) { + while (node->left) { + node = node->left; + } + return node; +} + +Node *insertNode(Node **root, int x) { + Node *ret; + + /* insert the data */ + if (*root == NULL) { + *root = (Node *)malloc(sizeof(Node)); + if (*root == NULL) { + printf("Can't allocate memory"); + exit(1); + } + (*root)->key = x; + (*root)->height = 0; + (*root)->left = NULL; + (*root)->right = NULL; + return *root; + } else if ((*root)->key > x) { + ret = insertNode(&(*root)->left, x); + } else if ((*root)->key < x) { + ret = insertNode(&(*root)->right, x); + } + + /* handle the unbalance problem */ + (*root)->height = + 1 + max(getHeight((*root)->left), getHeight((*root)->right)); + + int balance = getBalance(*root); + + /* case 1 left left unbalance */ + if (balance > 1 && getBalance((*root)->left) >= 0) { + *root = rightRotate(*root); + } + + /* case 2 left right unbalance */ + if (balance > 1 && getBalance((*root)->left) < 0) { + (*root)->left = leftRotate((*root)->left); + *root = rightRotate(*root); + } + + /* case 3 right left unbalance */ + if (balance < -1 && getBalance((*root)->right) > 0) { + (*root)->right = rightRotate((*root)->right); + *root = leftRotate(*root); + } + + /* case 4 right right unbalance */ + if (balance < -1 && getBalance((*root)->right) <= 0) { + *root = leftRotate(*root); + } + + return ret; +} + +Node *deleteNode(Node **root, int x) { + Node *tmp = *root; + + if (*root == NULL) + return NULL; + + if (x < (*root)->key) { + tmp = deleteNode(&(*root)->left, x); + } else if (x > (*root)->key) { + tmp = deleteNode(&(*root)->right, x); + } else { + if ((*root)->left == NULL || (*root)->right == NULL) { + Node *child = (*root)->left != NULL ? (*root)->left : (*root)->right; + + /* no child case */ + if (child == NULL) { + *root = NULL; + return tmp; + } else { + (*root)->key = child->key; + if ((*root)->left && + /* left child case */ + (*root)->left->key == child->key) { + tmp = deleteNode(&(*root)->left, child->key); + } else if ((*root)->right && + /* right child case */ + (*root)->right->key == child->key) { + tmp = deleteNode(&(*root)->right, child->key); + } + } + /* two child case */ + } else { + Node *child = minNode((*root)->right); + (*root)->key = child->key; + tmp = deleteNode(&(*root)->right, child->key); + } + } + + if ((*root) == NULL) { + return *root; + } + + int balance = getBalance(*root); + + (*root)->height = + 1 + max(getHeight((*root)->left), getHeight((*root)->right)); + + /* case 1 left left unbalance */ + if (balance > 1 && getBalance((*root)->left) >= 0) { + *root = rightRotate(*root); + } + + /* case 2 left right unbalance */ + if (balance > 1 && getBalance((*root)->left) < 0) { + (*root)->left = leftRotate((*root)->left); + *root = rightRotate(*root); + } + + /* case 3 right left unbalance */ + if (balance < -1 && getBalance((*root)->right) > 0) { + (*root)->right = rightRotate((*root)->right); + *root = leftRotate(*root); + } + + /* case 4 right right unbalance */ + if (balance < -1 && getBalance((*root)->right) <= 0) { + *root = leftRotate(*root); + } + + return tmp; +} + +void destroyTree(Node *root) { + if (root == NULL) { + return; + } + + destroyTree(root->left); + destroyTree(root->right); + + free(root); +}