ADT - AVL-Tree (平衡二叉树)
Posted darkchii
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ADT - AVL-Tree (平衡二叉树)相关的知识,希望对你有一定的参考价值。
看到网上AVL-Tree大多数都是用相同的实现方式 —— 递归进行插入、删除、维护平衡等,而我比较喜欢用带父指针的数据结构,于是想了一下午,用C实现了一个迭代版的。
由于没有暂时没有好的画二叉树的工具,所以暂时不做详细解释了(没有配图实在没说服力)。
目前发现graphviz还行,准备简单学一下,等有了配图再解释。
code:
#include <stdio.h> #include <stdlib.h> #include <conio.h> #define max(a, b) ((a) > (b) ? (a) : (b)) typedef struct BaseNode { int val; int height; struct BaseNode * left; struct BaseNode * right; struct BaseNode * parent; } avl_tree; avl_tree* fixup_insert_avltree(avl_tree* root, avl_tree* node); avl_tree* fixup_erase_avltree(avl_tree* root, avl_tree* node); avl_tree* search(avl_tree* node, int x); void initializtion(avl_tree** root) { (*root) = NULL; } int height(avl_tree* node) { if (node == NULL) return -1; else return node->height; } void fixup_height(avl_tree* node) { int LeftHeight = height(node->left); int RightHeight = height(node->right); if (LeftHeight > RightHeight) node->height = LeftHeight + 1; else node->height = RightHeight + 1; } int balance(avl_tree* node) { if (node == NULL) return 0; else return height(node->left) - height(node->right); } avl_tree* parent(avl_tree * node) { if (node == NULL) return NULL; else return node->parent; } avl_tree* grandparent(avl_tree * node) { avl_tree* pptr = parent(node); if (pptr == NULL) return NULL; else return pptr->parent; } avl_tree* left_rotate(avl_tree* root, avl_tree* node) { avl_tree * x = node; avl_tree * y = node->right; x->right = y->left; if (y->left != NULL) y->left->parent = x; y->parent = x->parent; if (x->parent == NULL) root = y; else if (x == x->parent->left) x->parent->left = y; else x->parent->right = y; y->left = x; x->parent = y; fixup_height(x); fixup_height(y); return root; } avl_tree* right_rotate(avl_tree* root, avl_tree* node) { avl_tree* x = node; avl_tree* y = node->left; x->left = y->right; if (y->right != NULL) y->right->parent = x; y->parent = x->parent; if (x->parent == NULL) root = y; else if (x == x->parent->left) x->parent->left = y; else x->parent->right = y; y->right = x; x->parent = y; fixup_height(x); fixup_height(y); return root; } avl_tree* left_right_rotate(avl_tree* root, avl_tree* node) { avl_tree * x = node; avl_tree * y = node->left; root = left_rotate(root, y); root = right_rotate(root, x); return root; } avl_tree* right_left_rotate(avl_tree* root, avl_tree* node) { avl_tree * x = node; avl_tree * y = node->right; root = right_rotate(root, y); root = left_rotate(root, x); return root; } void insert(avl_tree** root, int x) { avl_tree* nn = (avl_tree*)malloc(sizeof(avl_tree)); nn->left = nn->right = NULL; nn->val = x; nn->height = 0; avl_tree* p = (*root); avl_tree* q = NULL; while (p != NULL) { q = p; if (p->val > x) p = p->left; else p = p->right; } nn->parent = q; if (q == NULL) (*root) = nn; else if (q->val > x) q->left = nn; else q->right = nn; avl_tree * temp = nn; while (temp != NULL) { fixup_height(temp); temp = temp->parent; } *root = fixup_insert_avltree(*root, nn); } avl_tree* fixup_insert_avltree(avl_tree* root, avl_tree* node) { while (node != NULL) { avl_tree* gpptr = grandparent(node); avl_tree* gppptr = parent(gpptr); if ((balance(gpptr) > 1 || balance(gpptr) < -1)) { if (parent(node) == gpptr->left && node == parent(node)->left) root = right_rotate(root, gpptr); else if (parent(node) == gpptr->left && node == parent(node)->right) root = left_right_rotate(root, gpptr); else if (parent(node) == gpptr->right && node == parent(node)->right) root = left_rotate(root, gpptr); else root = right_left_rotate(root, gpptr); while (gppptr != NULL) { fixup_height(gppptr); gppptr = gppptr->parent; } } node = parent(node); } return root; } avl_tree* get_min_node(avl_tree* node) { avl_tree* mnode = node; if (mnode != NULL) while (mnode->left != NULL) mnode = mnode->left; return mnode; } avl_tree* get_max_node(avl_tree* node) { avl_tree* mnode = node; if (mnode != NULL) while (mnode->right != NULL) mnode = mnode->right; return mnode; } avl_tree* transform(avl_tree* root, avl_tree* ernode, avl_tree* node) { if (ernode->parent == NULL) root = node; else if (ernode == parent(ernode)->left) parent(ernode)->left = node; else parent(ernode)->right = node; if (node != NULL) node->parent = parent(ernode); return root; } void erase(avl_tree** root, int x) { avl_tree* node = search(*root, x); avl_tree* nptr; if (node == NULL) return ; if (node->left == NULL) { nptr = parent(node); *root = transform(*root, node, node->right); } else if (node->right == NULL) { nptr = parent(node); *root = transform(*root, node, node->left); } else { avl_tree* mn = get_min_node(node->right); if (parent(mn) == node) nptr = mn; else { nptr = parent(mn); *root = transform(*root, mn, mn->right); mn->right = node->right; if (mn->right != NULL) mn->right->parent = mn; } *root = transform(*root, node, mn); mn->left = node->left; if (mn->left != NULL) mn->left->parent = mn; } avl_tree* checknode = nptr; while (checknode != NULL) { fixup_height(checknode); checknode = checknode->parent; } *root = fixup_erase_avltree(*root, nptr); free(node); node = NULL; } avl_tree* fixup_erase_avltree(avl_tree* root, avl_tree* node) { while (node != NULL) { if (balance(node) > 1) { if (balance(node->left) > 0) root = right_rotate(root, node); else root = left_right_rotate(root, node); } else if (balance(node) < -1) { if (balance(node->right) < 0) root = left_rotate(root, node); else root = right_left_rotate(root, node); } node = node->parent; if (node != NULL) fixup_height(node); } return root; } avl_tree* search(avl_tree* node, int x) { if (node == NULL) return NULL; else if (node->val > x) return search(node->left, x); else if (node->val < x) return search(node->right, x); else return node; } void inorder(avl_tree* node) { if (node == NULL) { inorder(node->left); printf("%d ", node->val); inorder(node->right); } } int degree(avl_tree* node) { if (node == NULL) return 0; return degree(node->left) + degree(node->right) + 1; } int depth(avl_tree* node) { if (node == NULL) return 0; return max(depth(node->left), depth(node->right)) + 1; } void checkbalance(avl_tree* node) { if (node == NULL) { checkbalance(node->left); printf("%d --- 高度:%d --- 平衡度:%d\n", node->val, node->height, balance(node)); checkbalance(node->right); } } void destory(avl_tree** node) { if ((*node) != NULL) { destory(&(*node)->left); destory(&(*node)->right); free((*node)); } } int main() { avl_tree* root, * node; int x; char ch; initializtion(&root); puts("1> 添加 2> 删除"); puts("3> 查找 4> 查看"); puts("5> 个数 6> 深度"); puts("7> 平衡 8> 退出"); while ((ch = getch()) != ‘8‘) { switch (ch) { case ‘1‘: puts("输入:"); scanf("%d", &x); insert(&root, x); break; case ‘2‘: puts("输入:"); scanf("%d", &x); erase(&root, x); break; case ‘3‘: puts("输入:"); scanf("%d", &x); if ((node = search(root, x)) != NULL) printf("%d\n", node->val); break; case ‘4‘: puts("显示数据:"); inorder(root); printf("\n"); break; case ‘5‘: printf("\n当前数据个数:%d\n", degree(root)); break; case ‘6‘: printf("\n当前树深度:%d\n", depth(root)); break; case ‘7‘: puts("平衡检查:"); checkbalance(root); break; } } destory(&root); return 0; }
以上是关于ADT - AVL-Tree (平衡二叉树)的主要内容,如果未能解决你的问题,请参考以下文章