以前學習AVL樹,便照着書上(《Data structure and program design in C++》)的插入代碼敲了一遍加深印象(去掉書上的繼承)。ios
1.AVL樹是一種平衡二叉樹,經過保持每個節點的兩棵子樹的高度差不能超過1來保持樹的平衡性。函數
2.平衡性的保持:當插入新節點時,就可能破壞樹的平衡性,針對某一個平衡性被破壞的節點的平衡操做(假設子樹已經平衡,遞歸操做)有4種狀況:學習
case1:插入後左子樹更高且左子樹的左子樹比右子樹高,此時進行右旋操做測試
case2:插入後左子樹更高且左子樹的右子樹比左子樹高,此時進行雙旋轉操做spa
case3:插入後右子樹更高且右子樹的右子樹比左子樹高,此時進行左旋操做code
case4:插入後右子樹更高且右子樹的左子樹比右子樹高,此時進行雙旋轉操做blog
其實只須要分紅case1和case2兩種狀況,case3 和case4只是相反的位置而已繼承
3.代碼實現:遞歸
1)插入操做insert()函數調用avl_insert()函數ci
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