AVL树
2013-12-03 01:55 凝月流风 阅读(276) 评论(1) 编辑 收藏 举报
之前学习AVL树,便照着书上(《Data structure and program design in C++》)的插入代码敲了一遍加深印象(去掉书上的继承)。
1.AVL树是一种平衡二叉树,通过保持每一个节点的两棵子树的高度差不能超过1来保持树的平衡性。
2.平衡性的保持:当插入新节点时,就可能破坏树的平衡性,针对某一个平衡性被破坏的节点的平衡操作(假设子树已经平衡,递归操作)有4种情况:
case1:插入后左子树更高且左子树的左子树比右子树高,此时进行右旋操作
case2:插入后左子树更高且左子树的右子树比左子树高,此时进行双旋转操作
case3:插入后右子树更高且右子树的右子树比左子树高,此时进行左旋操作
case4:插入后右子树更高且右子树的左子树比右子树高,此时进行双旋转操作
其实只需要分成case1和case2两种情况,case3 和case4只是相反的位置而已
3.代码实现:
1)插入操作insert()函数调用avl_insert()函数
2)taller变量的设置非常巧妙,用以判断子树是否已经增高
3)一旦子树增高则判断是否需要进行平衡性操作
4)以下代码只实现插入操作,中序遍历用以测试
#include <iostream> using namespace std; enum Balance_factor { left_higher, equal_height, right_higher }; template<class Entry> struct Avl_Node { Entry data; Balance_factor balance; Avl_Node* left; Avl_Node* right; Avl_Node(Entry& x) { data = x; left = NULL; right = NULL; balance = equal_height; } Avl_Node() { left = right = NULL; balance = equal_height; } Balance_factor get_balance() { return balance; } void set_balance(Balance_factor x) { balance = x; } }; template<class Entry> class AVL_Tree { public: AVL_Tree(); bool insert(Entry& x); bool Remove(Entry& x); void Inorder(); //中序遍历 void recursive_inorder(Avl_Node<Entry>*); protected: Avl_Node<Entry>* root; bool avl_insert(Avl_Node<Entry>* &subroot, Entry& newdata, bool &taller); void rotate_left(Avl_Node<Entry>* &subroot); //左旋 void rotate_right(Avl_Node<Entry>* &subroot); //右旋 void left_balance(Avl_Node<Entry>* &subroot); //操作左子树保持平衡 void right_balance(Avl_Node<Entry>* &subroot); //操作右子树保持平衡 }; //构造函数 template<class Entry> AVL_Tree<Entry>::AVL_Tree() { root = NULL; } //插入数据 template<class Entry> bool AVL_Tree<Entry>::insert(Entry& x) { bool taller; return avl_insert(root, x, taller); } //删除数据 template<class Entry> bool AVL_Tree<Entry>::Remove(Entry& x) { } template<class Entry> bool AVL_Tree<Entry>::avl_insert(Avl_Node<Entry>* &subroot, Entry& newdata, bool &taller) { bool result = true; if (subroot == NULL) { subroot = new Avl_Node<Entry>(newdata); } else if (newdata < subroot->data) { //插入到左子树 result = avl_insert(subroot->left, newdata, taller); //插入到子树完成后判断子树高度是否增加,若增加,则可能导致不平衡,进行平衡处理 if (taller) { switch (subroot->get_balance()) { case left_higher : //若原来左边更高,在左子树插入后必然使得左边继续增高,导致不平衡,必须进行平衡操作 left_balance(subroot); taller = false; break; case equal_height : //若原来两边一样高,那么插入一个可以继续保持差值为1的平衡性,高度必定增加 subroot->set_balance(left_higher); break; case right_higher: //若原来右子树更高,那么增加左子树高度可以使树两边高度一致 taller = false; subroot->set_balance(equal_height); break; } } } else { result = avl_insert(subroot->right, newdata, taller); if (taller) { switch (subroot->get_balance()) { case left_higher: taller = false; subroot->set_balance(equal_height); break; case equal_height : subroot->set_balance(right_higher); break; case right_higher : right_balance(subroot); taller = false; break; } } } return result; } //左旋操作 template<class Entry> void AVL_Tree<Entry>::rotate_left(Avl_Node<Entry>* &subroot) { if (subroot == NULL || subroot->right == NULL) { cout << "subroot or subroot->right is NULL" << endl; } else { Avl_Node<Entry>* right_tree = subroot->right; subroot->right = right_tree->left; right_tree->left = subroot; subroot = right_tree; } } //右旋操作 template<class Entry> void AVL_Tree<Entry>::rotate_right(Avl_Node<Entry>* &subroot) { if (subroot == NULL || subroot->left == NULL) { cout << "subroot of subroot->left is NULL" << endl; } else { Avl_Node<Entry>* left_tree = subroot->left; subroot->left = left_tree->right; left_tree->right = subroot; subroot = left_tree; } } //重点,保持树的平衡操作,left_balance()函数为左子树过高时进行,right_balance()相反 template<class Entry> void AVL_Tree<Entry>::left_balance(Avl_Node<Entry>* &subroot) { Avl_Node<Entry>* left_tree = subroot->left; switch (left_tree->get_balance()) { case left_higher : //case1 subroot->set_balance(equal_height); left_tree->set_balance(equal_height); rotate_right(subroot); break; case equal_height : //error cout << "WARNING: program error detected in left_balance" << endl; case right_higher : //case 2 : double rotation Avl_Node<Entry>* subtree = left_tree->right; switch (subtree->get_balance()) { case left_higher : subroot->set_balance(right_higher); left_tree->set_balance(equal_height); break; case equal_height : subroot->set_balance(equal_height); left_tree->set_balance(equal_height); break; case right_higher : subroot->set_balance(equal_height); left_tree->set_balance(left_higher); } subtree->set_balance(equal_height); rotate_left(left_tree); rotate_right(subroot); break; } } template<class Entry> // The same as left_balance void AVL_Tree<Entry>::right_balance(Avl_Node<Entry>* &subroot) { Avl_Node<Entry>* right_tree = subroot->right; switch (right_tree->get_balance()) { case right_higher : //case3 subroot->set_balance(equal_height); right_tree->set_balance(equal_height); rotate_left(subroot); case equal_height : //error cout << "WARNING: program error detected in left_balance" << endl; case left_higher : //case4 Avl_Node<Entry>* subtree = right_tree->left; switch (subtree->get_balance()) { case left_higher : subroot->set_balance(equal_height); right_tree->set_balance(right_higher); break; case equal_height : subroot->set_balance(equal_height); right_tree->set_balance(equal_height); break; case right_higher : subroot->set_balance(left_higher); right_tree->set_balance(equal_height); break; } subtree->set_balance(equal_height); rotate_right(right_tree); rotate_left(subroot); break; } } //Test:inorder traversal template<class Entry> void AVL_Tree<Entry>::Inorder() { recursive_inorder(root); } template<class Entry> void AVL_Tree<Entry>::recursive_inorder(Avl_Node<Entry>* subroot) { if (subroot != NULL) { recursive_inorder(subroot->left); cout << subroot->data << endl; recursive_inorder(subroot->right); } } int main() { AVL_Tree<int> avl; for (int i = 0; i < 10; i++) { int u; cin >> u; avl.insert(u); } avl.Inorder(); return 0; }
若代码有误望能指点,thanks
Next step:SPLY Tree