日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++实现平衡二叉树

發布時間:2025/7/14 c/c++ 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++实现平衡二叉树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.概念

平衡二叉樹(AVL Tree)首先要滿足二叉樹的定義,如下

  • 二叉排序樹或者是一棵空樹,或者是具有下列性質的二叉樹:
  • 若左子樹不空,則左子樹上所有結點的值均小于它的根結點的值;
  • 若右子樹不空,則右子樹上所有結點的值均大于它的根結點的值;
  • 左、右子樹也分別為二叉排序樹;
  • 沒有鍵值相等的節點。
  • 平衡度是左子樹高度減去右子樹高度,平衡度只能是-1,+1,0
下圖給出了一個非平衡二叉排序樹和平衡二叉排序樹 說明:結點上方的數字是平衡度(平衡因子),a圖9結點左子樹比右子樹高2,不滿足AVL Tree的定義,所以是非平衡樹 b圖所有結點度數絕對值沒有超過1,所以滿足平衡樹的定義,是平衡樹
  • 危機結點是指平衡度為1,有可能破壞平衡樹的結點
  • 左改組是指新結點插入到危機結點的左樹下
  • 右改組是指新新結點插入到危機結點的右子樹下
  • LL是新結點插入在危機節點的左子樹的左子樹上
  • LR是新結點插入在危機節點的左子樹的右子樹上
  • RR是新結點插入在危機節點的右子樹的右子樹上
  • RL是新結點插入在危機節點的右子樹的左子樹上

2.代碼實現

當前樹的結構

?? ??? ???? 11
?? ??? ?? /?? \
?? ??? ?7?? ??? 15
?? ??? / \??? /? \
?? ?? 3?? ?? 9? 14?? ?? 18
???? / \???? /??? / \
??? 1?? 5?? ?12?? 16?? ? 20
?? ??? ??? ??? ????? /
?? ??? ??? ??? ??? 26

2.1 定義平衡樹結點:

平衡因子可以是右子樹高度減去左子樹高度,不同的教材定義不一樣,我這里按照左樹-右樹來做

template<class K, class V> struct AVLTreeNode {K _key; //樹權值 V _value;int _bf; //平衡因子 -1,0,1 (每個節點的平衡因子等于左子樹的高度減去右子樹的高度) //有的教材定義平衡度是左子樹高度減去右子樹,都是可以的AVLTreeNode<K, V>* _parent; //指向父節點的指針AVLTreeNode<K, V>* _left; //指向左孩子的指針AVLTreeNode<K, V>* _right; //指向右孩子的指針 AVLTreeNode(const K& key = K(), const V& value = V()):_key(key), _value(value), _bf(0), _parent(NULL), _left(NULL), _right(NULL){} };

2.2 左改組圖解

左右改組是為了方便我們插入刪除的時候保持二叉樹平衡而引入的概念

左改組LL型和LR(a),LR(b),LR(c)型圖解

2.3 左改組LL型

首先聲明一個構造的左子樹,subL其實就是危機結點,subLR是危機節點的右子樹,ppNode是祖先節點

構建parent子樹,將parent和subL連接起來

如果祖先結點為空,將當前結點subL置為根節點,請參見上圖(a‘)的情況,B是危機結點,調整過后變成了根節點

否則祖父結點賦給subL的父結點,判斷父節點是否是祖先結點的左子樹,是的話,用構造的左子樹替代之

不是就用subL替代祖先節點的右子樹

//左改組LL型 template<class K, class V> void AVLTree<K, V>::_RotateLL(AVLTreeNode<K, V>*& parent) {AVLTreeNode<K, V>* subL = parent->_left; //構造的左子樹AVLTreeNode<K, V>* subLR = subL->_right;//subL的右子樹AVLTreeNode<K, V>* ppNode = parent->_parent;//標記祖先節點//1.構建parent子樹 將parent和subLR鏈接起來parent->_left = subLR;if (subLR) subLR->_parent = parent;//2.構建subL子樹 將subL與parent鏈接起來subL->_right = parent;parent->_parent = subL;//3.將祖先節點與subL鏈接起來if (ppNode == NULL){ //如果祖先為NULL,說明當前subL節點為根節點subL->_parent = NULL;_root = subL;}else{subL->_parent = ppNode;if (ppNode->_left == parent)ppNode->_left = subL;else if (ppNode->_right == parent)ppNode->_right = subL;}//4.重置平衡因子parent->_bf = 0;subL->_bf = 0;//5.更新subL為當前父節點parent = subL; }

2.4 左改組LR(a)、LR(b)和LR(c)型

pNode是當前父節點,subR是構造的右子樹,subLR是subR的左子樹

對當前父節點LL左改組,再右改組

根據平衡因子判斷是LR什么類型,請參見上圖圖解(b),(c),(d)的情況

//左改組LR型 template<class K, class V> void AVLTree<K, V>::_RotateLR(AVLTreeNode<K, V>*& parent) {AVLTreeNode<K, V>* pNode = parent;AVLTreeNode<K, V>* subR = parent->_right;AVLTreeNode<K, V>* subLR = subR->_left;int bf = subLR->_bf;_RotateLL(parent->_right);_RotateRR(parent);//LR(b)型if (bf == -1){pNode->_bf = 0;subR->_bf = 1;}//LR(a)型else if (bf == 1){pNode->_bf = -1;subR->_bf = 0;}//LR(c)型else{pNode->_bf = 0;subR->_bf = 0;} }

?右改組和左改組鏡像對稱,反過來就行了

2.5 插入函數

AVL樹是空,將當前結點直接置為根節點

AVL樹在滿足平衡度的要求下,和二叉排序樹一致,key小于當前結點,轉到當前結點左子樹,key大于當前結點,轉到當前結點右子樹

將parent的左子樹賦予當前結點,更新平衡因子,_bf++

將parent的右子樹賦予當前結點,更新平衡因子,_bf--

如果合法,即平衡因子=0,終止當前循環

如果當前結點是危機結點,即平衡度絕對值等于1,當前結點往上回溯,變成父節點,繼續檢查它的平衡度

接下來是平衡異常的情況,父結點平衡度為2,當前結點(危機結點)平衡度為1,進入左改組LL,LL介紹參考2.2 左改組LL

當前結點平衡度為-1,進入左改組LR,LR介紹參考2.3 左改組LR

右改組的情況類似

template<class K, class V> bool AVLTree<K, V>::Insert(const K& key, const V& value) {//1.空樹if (_root == NULL){_root = new AVLTreeNode<K, V>(key, value);return true;}//2.AVL樹不為NULLAVLTreeNode<K, V>* parent = NULL;AVLTreeNode<K, V>* cur = _root;//找到數據插入位置while (cur){if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key > key){parent = cur;cur = cur->_left;}else{return false;}}//插入數據cur = new AVLTreeNode<K, V>(key, value);cur->_parent = parent;if (parent->_key > key)parent->_left = cur;elseparent->_right = cur;while (parent){//更新平衡因子if (cur == parent->_left)parent->_bf++;else if (cur == parent->_right)parent->_bf--;//檢驗平衡因子是否合法if (parent->_bf == 0)break;else if (parent->_bf == -1 || parent->_bf == 1){ // 回溯上升 更新祖父節點的平衡因子并檢驗合法性cur = parent;parent = cur->_parent;}// 2 -2 平衡因子不合法 需要進行旋轉 降低高度else {if (parent->_bf == -2){if (cur->_bf == -1)_RotateRR(parent);else_RotateLR(parent);}else if (parent->_bf == 2){if (cur->_bf == 1)_RotateLL(parent);else_RotateRL(parent);}break;}} }

?2.6 遍歷方法

//中序遍歷 template<class K, class V> void AVLTree<K, V>::_InOrder(AVLTreeNode<K, V>* root) {if (root == NULL)return;_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right); } //前序遍歷 template<class K, class V> void AVLTree<K, V>::_PreOrder(AVLTreeNode<K, V>* root) {if (root == NULL)return;cout << root->_key << " ";_PreOrder(root->_left);_PreOrder(root->_right); } //后序遍歷 template<class K, class V> void AVLTree<K, V>::_PostOrder(AVLTreeNode<K, V>* root) {if (root == NULL)return;_PostOrder(root->_left);_PostOrder(root->_right);cout << root->_key << " "; }

3.運行和源碼

運行效果如下

源代碼:https://github.com/cjy513203427/C_Program_Base/tree/master/61.%E5%B9%B3%E8%A1%A1%E4%BA%8C%E5%8F%89%E6%A0%91/61.%E5%B9%B3%E8%A1%A1%E4%BA%8C%E5%8F%89%E6%A0%91

?

轉載于:https://www.cnblogs.com/Java-Starter/p/10192034.html

總結

以上是生活随笔為你收集整理的C++实现平衡二叉树的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。