亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

AVL樹的C++實現

2019-11-06 07:27:15
字體:
來源:轉載
供稿:網友

簡介

AVL樹本質上是一顆二叉搜索樹,但是它和普通的二叉搜索樹不同的是它的每一個結點的兩個子樹的高度差不超過一,所以AVL樹也叫做平衡二叉樹,如果刪除或者插入一個結點使其高度差變化,就要對其進行旋轉再使它平衡。這樣就解決了二叉搜索樹鏈表化后(類似下圖第三種情況)中各類操作中的時間復雜度的提高的狀況。

AVL樹

結構定義

和普通的二叉搜索樹一樣,AVL樹的結點中包含左右孩子結點,key值與value值,不同的是AVL樹中為了方便旋轉還添加了_parent(父節點),最后還有最重要的 _bf(平衡因子:右子樹高度-左子樹高度),用來判斷AVL是否平衡。當平衡因子大于等于二的時候就說明該結點不平衡需要旋轉操作。

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) {}};

AVL樹的旋轉

旋轉操作是AVL樹在插入或者刪除操作后要維持其平衡的一種手段。對于一個平衡的結點(-1<=_bf<=1)來說,由于任意的結點最多有兩個孩子,當插入或者刪除一個結點之后,其高度差有可能會變為2或者-2,此時失去平衡。具體可分為如下幾種情況: AVL樹的旋轉

第一種和第二種情況為對稱的兩種情況,以右旋為例,如下圖:

以插入一個結點舉例,當d結點為插入結點時,插入后發現a的_bf變為-2,AVL樹失去平衡,而a的左子樹b結點的平衡因子為-1,此時整棵樹就應該向右旋轉即順時針旋轉。

具體操作即讓b作為根結點同時也是a的父結點,a下移稱為b的右孩子,e結點按照二叉搜索樹的性質,key值比b的key值大又比a的key值小,所以把他放在a的左孩子。 右旋

代碼實現

void RotateR(Node* parent) {//右旋 Node* subL = parent->_left; Node* subLR = subL->_right; parent->_left = subLR; if (subLR) subLR->_parent = parent; subL->_right = parent; Node* ppNode = parent->_parent; parent->_parent = subL; if (parent == _root) { _root = subL; _root->_parent = NULL; } else { if (ppNode->_left == parent) { ppNode->_left = subL; } else { ppNode->_right = subL; } subL->_parent = ppNode; } parent->_bf = subL->_bf = 0; }

第三種情況和第四種情況也為對稱,以左右旋轉為例,如下圖: 還是以插入一個結點為例,當插入結點在d位置時,發現a的_bf為-2,而其左孩子的 _bf為1,這時我們發現單次的旋轉無法達到平衡,要經過兩次旋轉。 具體操作即先以b為根結點進行左旋,使e成為b的父結點,再根據二叉搜索樹的性質,使d成為b結點的右孩子。旋轉完成后則變成了第一種情況,再進行一次右旋轉,最后得到平衡樹。 左右旋

void RotateLR(Node* parent) {//左右 Node* subL = parent->_left; Node* subLR = subL->_right; int bf = subLR->_bf; RotateL(parent->_left); RotateR(parent); if (bf == 1) { subL->_bf = -1; parent->_bf = 0; } else if (bf == -1) { parent->_bf = 1; subL->_bf = 0; } else { parent->_bf = subL->_bf = 0; } subLR->_bf = 0; }

AVL樹的插入操作

AVL樹在插入的時候與二叉搜索樹相同,區別是在插入之后需要更新平衡因子,如果插入后AVL樹失衡,則要進行相應的旋轉來保持AVL樹的平衡。

bool Insert(const K& key, const V& value) { if (_root == NULL) { _root = new Node(key, value); return true; } Node* parent = NULL; Node* cur = _root; while(cur) {//找到要插入結點的父節點位置 if (key < cur->_key) { parent = cur; cur = cur->_left; } else if (key>cur->_key) { parent = cur; cur = cur->_right; } else { return false; } } //插入新結點 cur = new Node(key, value); if (key < parent->_key) { parent->_left = cur; cur->_parent = parent; } else { parent->_right = cur; cur->_parent = parent; } while (parent) {//調整平衡因子 if (parent->_left == cur) parent->_bf -= 1; else parent->_bf += 1; if (parent->_bf == 0) break; else if (parent->_bf == 1 || parent->_bf == -1) {//父結點的平衡因子變化,繼續向上更新 cur = parent; parent = cur->_parent; } else if (parent->_bf == 2 ||parent->_bf ==-2) { if (parent->_bf == 2) { if (parent->_bf == 2) { if (cur->_bf == 1) { RotateL(parent); } else { RotateRL(parent); } } else { if (cur->_bf == -1) { RotateR(parent); } else { RotateLR(parent); } } break; } } } }

AVL樹刪除結點

其實AVL樹的刪除操作與二叉搜索樹基本相同,區別是AVL樹在刪除后,要從其真正刪除結點的父結點向上調整平衡。并且要注意在刪除操作中時刻調整每個結點的平衡因子。 刪除

如圖:假定要刪除的結點為紅色結點,而在二叉搜索樹的刪除操作中,是把藍色結點替換掉紅色結點,真正刪除的是藍色結點,所以此時就應該從黃色結點的位置向上一層層調整平衡。

bool Remove(const K& key) { return _Remove(_root,key); } bool _Remove(Node* root,const K& key) {//與二叉搜索樹的刪除基本相同 if (root == NULL) return false; if (key < root->_key) { root->_bf += 1; return _Remove(root->_left, key); } else if (key>root->_key) { root->_bf -= 1; return _Remove(root->_right, key); } else { Node* del = root; if (root->_left == NULL) { root->_right->_parent = root->_parent; root = root->_right; } else if (root->_right == NULL) { root->_left->_parent = root->_parent; root = root->_left; } else { Node* subLeft = root->_right; while (subLeft->_left) { subLeft = subLeft->_left; } root->_key = subLeft->_key; root->_value = subLeft->_value; del = subLeft; subLeft = subLeft->_right; while (del->_parent) {//調整平衡,從要被真正delete的那個結點開始向上調整 if (del->_parent->_bf == 2 || del->_parent->_bf == -2) { if (del->_parent->_bf == 2) { if (del->_bf == 1) RotateL(del->_parent); else RotateRL(del->_parent); } else { if (del->_parent->_bf == -2) { if (del->_bf == 1) RotateR(del->_parent); else RotateLR(del->_parent); } } } else return true; } } delete del; return true; } }

判斷這棵樹是否為AVL樹

在這里我們給出了兩種方式來判斷,第一種方式是通過求樹的每個結點左右孩子的高度來計算平衡因子。

bool IsBalance() {//判斷是否平衡 return _IsBalance(_root); } size_t _Depth(Node* root) {//求深度 if (root == NULL) return 0; size_t leftDepth = _Depth(root->_left); size_t rightDepth = _Depth(root->_right); return leftDepth < rightDepth ? rightDepth+1 : leftDepth+1; } bool _IsBalance(Node* root) {//時間復雜度O(N2) if (root == NULL) return true; size_t leftH = _Depth(root->_left); size_t rightH = _Depth(root->_right); if ((rightH - leftH) != root->_bf) { cout << "平衡因子異常:" << root->_key << endl; } return abs(rightH - leftH) <= 1 && _IsBalance(root->_left) && _IsBalance(root->_right); }

第二種是直接在尋找每個節點左右葉結點的同時計算其平衡因子。這樣大大的提高了效率。使時間復雜度大大減小。

bool IsBalanceOP() {//判斷是否平衡 size_t depth= 0; return _IsBalanceOP(_root,depth); } bool _IsBalanceOP(Node* root, size_t& depth) {//時間復雜度O(N) if (root == NULL) { depth = 0; return true; } size_t leftDepth, rightDepth; if (_IsBalanceOP(root->_left, leftDepth) && _IsBalanceOP(root->_right, rightDepth)) { depth = leftDepth < rightDepth ? rightDepth + 1 : leftDepth + 1; return abs(leftDepth - rightDepth) < 2; } }
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩小视频在线观看| 岛国av一区二区在线在线观看| 视频在线观看一区二区| 午夜精品蜜臀一区二区三区免费| 97人人做人人爱| 97在线视频观看| 亚洲第一中文字幕在线观看| 韩国v欧美v日本v亚洲| 欧美一级大片在线免费观看| 98午夜经典影视| 97成人精品区在线播放| 91精品国产免费久久久久久| 亚洲japanese制服美女| 国产精选久久久久久| 国产精品专区第二| 91久久中文字幕| 福利二区91精品bt7086| 亚洲精品国产品国语在线| 国产亚洲精品激情久久| 国产欧美亚洲精品| 久久久中文字幕| 国产精品久久一区主播| 动漫精品一区二区| 国内精品久久久久影院 日本资源| 国产美女精品视频免费观看| 中文字幕日韩精品在线| 亚洲视频一区二区| 国产成人精品日本亚洲| 日韩在线一区二区三区免费视频| 日韩欧美第一页| 日韩欧美aⅴ综合网站发布| 精品久久久久久久久久久| 伊人久久久久久久久久久久久| 国产精品久久久久免费a∨大胸| 亚洲激情小视频| 91色p视频在线| 欧美多人爱爱视频网站| 日本中文字幕不卡免费| 91高清视频在线免费观看| 国产一区二区在线播放| 欧美精品www在线观看| 亚洲一区二区免费在线| 欧美电影免费观看高清完整| 午夜精品三级视频福利| 亚洲一品av免费观看| zzijzzij亚洲日本成熟少妇| 欧美电影免费观看电视剧大全| 激情亚洲一区二区三区四区| 日韩高清电影免费观看完整| 97婷婷大伊香蕉精品视频| 久久91精品国产91久久跳| 欧美丰满老妇厨房牲生活| 欧美激情国产日韩精品一区18| 精品久久久久久电影| 国产亚洲一级高清| 欧美一区二区三区……| 91产国在线观看动作片喷水| 久久亚洲精品中文字幕冲田杏梨| 欧美黑人巨大xxx极品| 欧美视频在线观看 亚洲欧| 国产一区二区三区网站| 国产91在线视频| 亚洲在线观看视频| 蜜臀久久99精品久久久无需会员| 成人性教育视频在线观看| 成人97在线观看视频| 亚洲最大成人在线| 国产精品久久久久久av下载红粉| 国产精品 欧美在线| 亚洲国产成人精品久久久国产成人一区| 一区三区二区视频| 国产91色在线|免| 国内伊人久久久久久网站视频| 欧美性xxxx极品高清hd直播| 日韩中文字幕免费看| 欧美一级黑人aaaaaaa做受| 久久精品国产清自在天天线| 久久久久久久久久久久久久久久久久av| 欧美日韩激情美女| 亚洲精品videossex少妇| 91爱爱小视频k| 日韩精品在线免费播放| 国产精品视频区1| 亚洲人av在线影院| 亚洲肉体裸体xxxx137| 91精品视频播放| 92看片淫黄大片欧美看国产片| 中文字幕欧美亚洲| 91老司机在线| 欧美一级大片在线观看| 57pao成人永久免费视频| 亚洲 日韩 国产第一| 亚洲精品美女免费| 欧美一区视频在线| 国产精品入口夜色视频大尺度| 国产三级精品网站| 91在线视频成人| 成人h猎奇视频网站| 久久99视频精品| 国产精品扒开腿做爽爽爽的视频| 在线播放国产一区二区三区| 久久99国产综合精品女同| 国产精品一区二区av影院萌芽| 亚洲一级免费视频| 久久久久久久国产精品视频| 久操成人在线视频| 久久在线视频在线| 国产精品视频一区国模私拍| 日韩国产在线播放| 国产精品自产拍在线观看中文| 丁香五六月婷婷久久激情| 亚洲综合小说区| 91丝袜美腿美女视频网站| 国产欧美久久久久久| 亚洲美女福利视频网站| 激情懂色av一区av二区av| 日韩av大片免费看| 综合久久五月天| 久久九九国产精品怡红院| 国产成人精品在线视频| 欧美国产乱视频| 久久人人爽人人| 亚洲视频在线免费观看| 欧美激情一区二区三区在线视频观看| 九九久久久久99精品| 日韩中文字幕第一页| 日韩一区视频在线| 亚洲www在线| 人体精品一二三区| 国产91精品不卡视频| 亚洲精品美女久久久| 美女撒尿一区二区三区| 欧美日韩视频在线| 久久精品国产2020观看福利| 97视频色精品| 精品少妇v888av| 成人精品视频久久久久| 欧美成人免费大片| 欧美疯狂做受xxxx高潮| 最新国产成人av网站网址麻豆| 久久国产精品网站| 欧美最猛性xxxxx免费| 久久久噜噜噜久久中文字免| 成人精品视频在线| 美女撒尿一区二区三区| 欧美老女人性视频| 亚洲在线视频观看| 国产精品一区二区性色av| 久久久91精品| 亚洲乱码国产乱码精品精| …久久精品99久久香蕉国产| 亚洲国产91色在线| 91精品国产乱码久久久久久蜜臀| 美女视频久久黄| 亚洲日韩欧美视频一区| 欧美午夜宅男影院在线观看| 国产精品美女久久久久av超清| 日本久久中文字幕| 日韩一区视频在线| 久操成人在线视频| 久久久久久久久国产精品| 69久久夜色精品国产69乱青草| 国产不卡av在线| 81精品国产乱码久久久久久|