算法原理请参考《算法导论》,简单描述下:就是所有节点(根节点除外)的最大深度和最小深度之间的差小于2。
代码实现,只贴出和红黑树不同的类成员函数实现,其余都是和红黑树一样。
类声明
template <typename T> class avl_tree { public: typedef struct _avl_type { _avl_type(_avl_type *_left, _avl_type *_right, _avl_type *_p, int _bf, T k) : left(_left), right(_right), p(_p), bf(_bf), key(k) {} int bf;//当前结点左右子树的高度差 T key; _avl_type *left, *right, *p; }avl_type, *pavl_type; avl_tree(T *A, int n):root(NULL) { for (int i = 0; i < n; i++) avl_insert(A[i]); } ~avl_tree() { avl_empty(root); } void left_rotate(pavl_type x); void right_rotate(pavl_type x); pavl_type avl_max(pavl_type x); pavl_type avl_min(pavl_type x); pavl_type avl_search(T key); pavl_type avl_next(T key);//后趋 pavl_type avl_prev(T key);//前继 void avl_insert(T key); void avl_delete(T key); void avl_show(pavl_type x); pavl_type avl_root(); void avl_empty(pavl_type x); private: int avl_max_depth(pavl_type x); int avl_min_depth(pavl_type x); void avl_fixup(pavl_type x);//后续修复 pavl_type root; };
和红黑树不同的类成员函数实现
avl_insert成员函数
template <typename T> void avl_tree<T>::avl_insert(T key) { pavl_type y = NULL, x = root, z = new avl_type(NULL, NULL, NULL, 0, key); while (x != NULL) { y = x; if (key < x->key) x = x->left; else x = x->right; } z->p = y; if (y == NULL) root = z; else { if (key < y->key) y->left = z; else y->right = z; } avl_fixup(root);//插入和删除统一使用一个修复函数,和红黑树不同 }
avl_delete成员函数
template <typename T> void avl_tree<T>::avl_delete(T key) { pavl_type z = avl_search(key), y, x; if (z == NULL) return; if (z->left == NULL || z->right == NULL)//y是待删除的节点 y = z;//z有一个子节点 else y = avl_next(key);//z有两个子节点,后继和前趋保证了y有一个或没有子节点 if (y->left != NULL) x = y->left; else x = y->right; if (x != NULL) //存在一个子节点,先更正父子关系 x->p = y->p; if (y->p == NULL)//再决定是在左或者右节点 root = x; else { if (y->p->left == y) y->p->left = x; else y->p->right = x; } if (y != z)//处理两个子节点的交换 z->key = y->key; avl_fixup(root); delete y; }
avl_fixup成员函数,修复节点
template <typename T> void avl_tree<T>::avl_fixup(typename avl_tree<T>::pavl_type x) { if (x != NULL) { avl_fixup(x->left); avl_fixup(x->right);//采用后续修复节点 x->bf = avl_max_depth(x) - avl_min_depth(x);//自动更新 if (x->bf == 2) {//不平衡 if (avl_max_depth(x->right) > avl_max_depth(x->left)) {//右子树大 if (x->right->right) //右子树插入右孩子 left_rotate(x); else if (x->right->left && !x->right->right) {//右子树插入左孩子 right_rotate(x->right); left_rotate(x); } } else { if (x->left->left)//左子树插入左孩子 right_rotate(x); else if (x->left->right && !x->left->left) {//左子树插入右孩子 left_rotate(x->left); right_rotate(x); } } x = x->p; if (x) x->bf = avl_max_depth(x) - avl_min_depth(x); if (x && x->left) x->left->bf = avl_max_depth(x->left) - avl_min_depth(x->left); if (x && x->right) x->right->bf = avl_max_depth(x->right) - avl_min_depth(x->right); } } }
avl_max_depth成员函数,最大深度
template <typename T> int avl_tree<T>::avl_max_depth(typename avl_tree<T>::pavl_type x) { if (x == NULL) return 0; int l = avl_max_depth(x->left); int r = avl_max_depth(x->right); return (l > r ? l : r) + 1; }
avl_min_depth成员函数,最小深度
template <typename T> int avl_tree<T>::avl_min_depth(typename avl_tree<T>::pavl_type x) { if (x == NULL) return 0; int l = avl_min_depth(x->left); int r = avl_min_depth(x->right); return (l < r ? l : r) + 1; }
avl_show成员函数,打印AVL树信息,保证函数都正确
template <typename T> void avl_tree<T>::avl_show(typename avl_tree<T>::pavl_type x) { if (x != NULL) { avl_show(x->left); if (x==root) printf("[root]bf=%d, key=%d(%d,%d)\n", x->bf, x->key, avl_max_depth(x),avl_min_depth(x)); else printf("bf=%d, key=%d(%d,%d)\n", x->bf, x->key, avl_max_depth(x),avl_min_depth(x)); avl_show(x->right); } }
之前的修复成员函数,效率太低,给一个效率特别高的修复函数
插入后修复调用:avl_fixup_1(z);
删除后修复调用:avl_fixup_1(y->p);
template <typename T> void avl_tree<T>::avl_fixup_1(typename avl_tree<T>::pavl_type x) { while (x) { x->bf = avl_max_depth(x) - avl_min_depth(x);//自动更新 if (x->left) x->left->bf = avl_max_depth(x->left) - avl_min_depth(x->left); if (x->right) x->right->bf = avl_max_depth(x->right) - avl_min_depth(x->right); if (x != root && x->bf == 2) {//不平衡 if (avl_max_depth(x->right) > avl_max_depth(x->left)) {//右子树大 if (x->right->right) //右子树插入右孩子 left_rotate(x); else if (x->right->left && !x->right->right) {//右子树插入左孩子 right_rotate(x->right); left_rotate(x); } } else { if (x->left->left)//左子树插入左孩子 right_rotate(x); else if (x->left->right && !x->left->left) {//左子树插入右孩子 left_rotate(x->left); right_rotate(x); } } } x = x->p; } }
数据测试
输入数据:5 3 7 2 4 6 8 0 1 -1q
结果显示
其余数据,可以自己测试
5 6 -1 0 -6 -8 99 6q
12 8 18 5 11 17 4 2q
5 2 0 -6 -99 -5 5 1q
......
所有代码均经过测试,结果正确!