代碼詳解AVL樹的插入

來源:互聯網
上載者:User
AVL樹被稱為高度平衡的二叉搜尋樹,盡量降低二叉樹的高度,來保持二叉樹的平衡,減少樹的平均搜尋長度。

AVL樹的性質:1、左子樹和右子樹的高度之差(絕對值)不超過1

2、樹中的每棵子樹都是AVL樹,

3、每個節點都有一個平衡因子,取值為(-1,0,1),通過平衡因子來判斷樹的平衡。

AVL樹的插入需要考慮以下的幾種情況:(箭頭表示要插入的方向和節點)

第一種情況:插入的節點在20的右邊,但是這樣導致10的平衡因子大於1所以需要進行旋轉才能改變平衡因子

第二種情況:在左邊插入,導致平衡因子也不滿足條件,需要旋轉

第三種情況:插入的節點可能不構成單旋,所以需要雙旋來解決

第四種情況:與第三種情況相反的雙旋

如此通過旋轉就可以達到在插入的時候讓此二叉樹達到平衡。

實現代碼如下:

//main函數#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>#include<assert.h>using namespace std;#include"AVLTree.h"int main(){testAVLTree();system("pause");return 0;}


//AVLTree  ---->  被稱為高度平衡的二叉搜尋樹//使用三叉鏈來實現此二叉平衡搜尋樹//性質:左右高度差不超過1 && 該樹的左右子樹都為二叉平衡樹template<class K,class V>struct AVLTreeNode{AVLTreeNode<K, V>* _left;   AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;K _key;V _value;int _bf; // 平衡因子//建構函式AVLTreeNode(const K& key,const V& value) :_left(NULL), _right(NULL), _parent(NULL), _key(key), _value(value), _bf(0){}};template<class K,class V>class AVLTree{typedef AVLTreeNode<K,V> Node;public:AVLTree() :_root(NULL){}//使用非遞迴的插入bool Insert(const K& key, const V& value){//如果根節點不存在說明插入的節點是第一個節點,直接new 一個即可if (_root == NULL){_root = new Node(key, value);return true;}Node* cur = _root;Node* parent = NULL;while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key>key){parent = cur;cur = cur->_left;}else{return false;}}//走到這裡,說明這個節點不存在,先newcur = new Node(key, value);//比較插入節點的值與父節點的值,再考慮鏈上左還是右if (parent->_key < key){parent->_right = cur;cur->_parent = parent;}else if (parent->_key>key){parent->_left = cur;cur->_parent = parent;}else{while (parent){//判斷cur是插在了parent的左邊還是右邊,再判斷平衡因子是++還是--if (cur == parent->_left){parent->_bf--;}else{parent->_bf++;}//++或--之後,判斷平衡因子是否等於2或等於-2if (parent->_bf == 0)    //等於0說明沒有變,則跳出迴圈{break;}else if (parent->_bf == 1 || parent->_bf == -1){cur = parent;parent = cur->_parent;}else if (parent->_bf == 2 || parent->_bf == -2)//如果等於2或者等於-2則不再插入,先調節為二叉平衡樹再插入{//根據平衡因子來判斷需要調整的樹是哪種類型,再選擇單旋還是雙旋//如果父節點的平衡因子等於2,說明右子樹比左子樹高,再判斷右子樹的子樹是在它的左邊還是右邊if (parent->_bf == 2){if (cur->_bf == 1){RotateL(parent);}else{RotateRL(parent);}}else{if (cur->_bf == -1)RotateR(parent);elseRotateLR(parent);}}}}return true;}//cur = parent;//右單旋void RotateR(Node* parent){//需要記錄parent上面是否還有父親節點Node* ppNode = parent->_parent;Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;//如果subLR存在  就將它的父親置為parentif (subLR)subLR->_parent = parent;subL->_right = parent;parent->_parent = subL;//如果parent等於根節點,說明已經到第一個節點,不需要調整,直接將subL作為根即可if (parent == _root){_root = subL;subL->_parent = NULL;}else   //如果還沒有到根節點還需要判斷parent是左還是右{if (ppNode->_left == parent)ppNode->_left = subL;else{ppNode->_right = subL;}subL->_parent = ppNode;}}//左單旋void RotateL(Node* parent){Node* ppNode = parent->_parent;Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;//判斷subRL是否存在if (subRL){subRL->_parent = parent;}subR->_left = parent;parent->_parent = subRL;if (_root == parent){_root = subR;subR->_parent = NULL;}else{if (ppNode->_left == parent)ppNode->_left = subR;elseppNode->_right = subR;subR->_parent = ppNode;}}//左右單旋void RotateLR(Node* parent){RotateL(parent->_right);RotateR(parent);}//右左單旋void RotateRL(Node* parent){RotateR(parent->_left);RotateL(parent);}void InOrder(){_InOrder(_root);cout << endl;}void _InOrder(Node* root){if (root == NULL)return;_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}bool IsBalance(){return _IsBalance(_root);}bool _IsBalance(Node* root){if (root == NULL)return;int leftheight = _Height(root->_left);int rightheight = _Height(root->_right);return abs(rightheight - leftheight) < 2 && _IsBalance(root->_left) && _IsBalance(root->_right);}size_t _Height(Node* root){if (root == NULL)return 0;size_t left = _Height(root->_left);size_t right = _Height(root->_right);return left > right ? left + 1 : right + 1;}private:Node* _root;};void testAVLTree(){AVLTree<int, int> t;int a[] = { 16,3,7,11,9,26,18,14,15};for (int i = 0; i < (sizeof(a) / sizeof(a[0])); i++){cout<<t.Insert(a[i], 0)<<endl;}t.InOrder();}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.