今天就跟大家聊聊有關(guān)數(shù)據(jù)結(jié)構(gòu)中的AVL樹是什么意思,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
創(chuàng)新互聯(lián)公司長期為上千客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺(tái),與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為玉屏企業(yè)提供專業(yè)的網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì),玉屏網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。
1、AVL樹簡介
AVL樹本質(zhì)上還是一棵二叉搜索樹,又稱高度平衡的二叉搜索樹。它能保持二叉樹的高度平衡,盡量降低二叉樹的高度,減少樹的平均搜索長度。對于二叉搜索樹的介紹和實(shí)現(xiàn),可查看本人上一篇博客。
2、AVL樹的特點(diǎn)
1)本身首先是一棵二叉搜索樹。
2)帶有平衡條件:每個(gè)結(jié)點(diǎn)的左右子樹的高度之差的絕對值(平衡因子)最多為1。
3)樹中的每個(gè)左子樹和右子樹都是AVL樹。
4)每個(gè)結(jié)點(diǎn)都有一個(gè)平衡因子,任一結(jié)點(diǎn)的平衡因子是-1,0,1.
注:結(jié)點(diǎn)的平衡因子 = 右子樹高度 - 左子樹高度
3、AVL樹的效率
一棵AVL樹有N個(gè)結(jié)點(diǎn),其高度可以保持在lgN,插入/刪除/查找的時(shí)間復(fù)雜度也是lgN。
AVL樹的復(fù)雜程度真是比二叉搜索樹高了整整一個(gè)數(shù)量級(jí)——它的原理并不難弄懂,但要把它用代碼實(shí)現(xiàn)出來還真的有點(diǎn)費(fèi)腦筋。下面我們來看看AVL樹實(shí)現(xiàn)的接口,通過三叉鏈進(jìn)行結(jié)點(diǎn)的實(shí)現(xiàn)。
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 = K(), const V& value = V())//加上K()和V(),可缺省構(gòu)造 :_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) {} void Insert(const K& key, const V& value); Node* Find(const K& key); int Height(); bool IsBalance(); void PrintAVLTree(); private: Node* _Find(Node* root, const K& key); void _RotateL(Node*& parent); void _RotateR(Node*& parent); void _RotateLR(Node*& parent); void _RotateRL(Node*& parent); int _Height(Node* root); bool _IsBalance(Node* root); void _PrintAVLTree(Node* root); protected: Node* _root; };
下面對插入進(jìn)行元素的分析:
1)判斷樹是否為空,為空時(shí),新建根結(jié)點(diǎn)。
2)查找插入的key是否存在,存在就退出函數(shù),不存在就執(zhí)行3)。
3)找到插入key的位置,然后插入結(jié)點(diǎn)cur。
4)更新平衡因子:從cur開始向上其父結(jié)點(diǎn)進(jìn)行更新平衡因子,如果結(jié)點(diǎn)的平衡因子不滿足AVL樹,進(jìn)行旋轉(zhuǎn)調(diào)節(jié)平衡因子。
template<class K,class V> void AVLTree<K,V>::Insert(const K& key, const V& value) { if (_root == NULL) { _root = new Node(key, value); return; } if (Find(key))//存在key { return; } Node* prev = NULL; Node* cur = _root; while (cur)//插入key的位置cur { if (key < cur->_key) { prev = cur; cur = cur->_left; } else if (key > cur->_key) { prev = cur; cur = cur->_right; } } cur = new Node(key, value);//插如結(jié)點(diǎn)cur if (prev->_key > key) { prev->_left = cur; cur->_parent = prev; } else if (prev->_key < key) { prev->_right = cur; cur->_parent = prev; } //prev為cur的上一個(gè)結(jié)點(diǎn),即為cur是prev的父親結(jié)點(diǎn) prev = cur; cur = prev->_parent; while (cur) { //更新平衡因子:從插如的cur開始向上更新平衡因子 cur->_bf = _Height(cur->_right) - _Height(cur->_left); if (cur->_bf != -1 && cur->_bf != 1 && cur->_bf != 0)//不滿足AVL樹的結(jié)點(diǎn),進(jìn)行旋轉(zhuǎn)調(diào)節(jié)平衡因子 {//平衡因子為2時(shí),一定存在右子樹;平衡因子為-2時(shí),一定存在左子樹 //左單旋:2 1(平衡因子) if (cur->_bf == 2 && cur->_right->_bf == 1) { _RotateL(cur);//引用傳遞 } //右單旋:-2 -1 else if (cur->_bf == -2 && cur->_left->_bf == -1) { _RotateR(cur); } //左右旋轉(zhuǎn):-2 1 else if (cur->_bf == -2 && cur->_left->_bf == 1) { _RotateLR(cur); } //右左旋轉(zhuǎn):2 -1 else if (cur->_bf == 2 && cur->_right->_bf == -1) { _RotateRL(cur); } } prev = cur; cur = cur->_parent; } }
進(jìn)行旋轉(zhuǎn)調(diào)節(jié)平衡因子,分四種情況:
(1)左單旋:cur的平衡因子為2,cur->_right的平衡因子為1。
(2)右單旋:cur的平衡因子為-2,cur->_left的平衡因子為-1。
(3)左右旋轉(zhuǎn):cur的平衡因子為-2,cur->_left的平衡因子為1。
(4)右左旋轉(zhuǎn):cur的平衡因子為-2,cur->_right的平衡因子為-1。
左右旋轉(zhuǎn)和右左旋轉(zhuǎn)可通過調(diào)用左單旋和右單旋進(jìn)行,注意結(jié)束后重置平衡因子。
如果不是很清楚,可以自己畫圖進(jìn)行分析。
左單旋:
template<class K, class V> void AVLTree<K, V>::_RotateL(Node*& parent) { Node* subR = parent->_right; Node* subRL = subR->_left; parent->_right = subRL;//1 subR->_parent = parent->_parent;//1 subR->_left = parent;//2 parent->_parent = subR;//2 if (subRL)//注意不為空,進(jìn)行鏈接 subRL->_parent = parent; parent->_bf = subR->_bf = 0; //進(jìn)行subR的父親結(jié)點(diǎn)和subR的鏈接 if (subR->_parent == NULL)//為空時(shí),parent為根結(jié)點(diǎn),更改根結(jié)點(diǎn) _root = subR; else//不為空,進(jìn)行鏈接 { if (subR->_parent->_key > subR->_key) subR->_parent->_left = subR; else subR->_parent->_right = subR; } parent = subR; }
右單旋:
template<class K, class V> void AVLTree<K, V>::_RotateR(Node*& parent) { Node* subL = parent->_left; Node* subLR = subL->_right; //不能變換順序 parent->_left = subL->_right;//1 subL->_parent = parent->_parent;//1 subL->_right = parent;//2 parent->_parent = subL;//2 if (subLR)//注意不為空,進(jìn)行鏈接 subLR->_parent = parent; parent->_bf = subL->_bf = 0; //進(jìn)行subL的父親結(jié)點(diǎn)和subL的鏈接 if (subL->_parent == NULL)//為空時(shí),parent為根結(jié)點(diǎn),更改根結(jié)點(diǎn) _root = subL; else//不為空,進(jìn)行鏈接 { if (subL->_parent->_key > subL->_key) subL->_parent->_left = subL; else subL->_parent->_right = subL; } parent = subL; }
左右旋轉(zhuǎn):
template<class K, class V> void AVLTree<K, V>::_RotateLR(Node*& parent) { Node* pNode = parent;//需重新定義parent,在進(jìn)行左右旋轉(zhuǎn)后,parent指向發(fā)生了變化 Node* subLNode = pNode->_left; Node* subLRNode = subLNode->_right; _RotateL(parent->_left); _RotateR(parent); //在單旋時(shí),parent和subL的平衡因子都為0,在進(jìn)行左右旋轉(zhuǎn)和右左旋轉(zhuǎn)會(huì)出錯(cuò),故重新設(shè)置平衡因子 //subLRNode的平衡因子存在三種情況:為0,為-1,為1。subLRNode的平衡因子影響parent和subL的平衡因子 if (subLRNode->_bf == 1) { pNode->_bf = 1; subLNode->_bf = 0; } else if (subLRNode->_bf == -1) { pNode->_bf = 0; subLNode->_bf = -1; } else { parent->_bf = 0; subLNode->_bf = 0; } }
右左旋轉(zhuǎn):
template<class K, class V> void AVLTree<K, V>::_RotateRL(Node*& parent) { Node* pNode = parent; Node* subRNode = pNode->_right; Node* subRLNode = subRNode->_left; _RotateR(parent->_right); _RotateL(parent); if (subRLNode->_bf == 1) { pNode->_bf = -1; subRNode->_bf = 0; } else if (subRLNode->_bf == -1) { pNode->_bf = 0; subRNode->_bf = 1; } else { pNode->_bf = 0; subRNode->_bf = 0; } }
測試用例如下:
void AVLTreeTest() { AVLTree<int, int> avlt; //int arr[10] = { 16, 3, 7, 11, 9, 26, 18, 14, 15, 23 }; int arr[10] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 }; for (int i = 0; i < 10; ++i) { avlt.Insert(arr[i], i); avlt.PrintAVLTree(); } cout << avlt.IsBalance() << endl; }
看完上述內(nèi)容,你們對數(shù)據(jù)結(jié)構(gòu)中的AVL樹是什么意思有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。
本文標(biāo)題:數(shù)據(jù)結(jié)構(gòu)中的AVL樹是什么意思
瀏覽地址:http://aaarwkj.com/article12/pegegc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設(shè)、網(wǎng)站改版、品牌網(wǎng)站制作、做網(wǎng)站、企業(yè)建站、微信公眾號(hào)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)