《AVL樹完全解析:平衡之道與C++實現》

目錄

  1. AVL樹的核心概念
  2. 數據結構與節點定義
  3. 插入操作與平衡因子更新
  4. 旋轉操作:從理論到代碼
  5. 雙旋場景深度剖析
  6. 平衡檢測與測試策略
  7. 性能分析與工程實踐
  8. 總結

0.前置知識:BS樹

代碼實現部分對和BS樹相似的部分會省略。

1. AVL樹的核心概念

1.1 平衡二叉搜索樹的必要性

普通二叉搜索樹(BST)在極端情況下會退化為鏈表,時間復雜度惡化至O(N)。AVL樹通過強制平衡約束,將樹高度嚴格控制在O(log N),確保所有操作的高效性。

1.2 AVL樹的定義

  • 平衡條件:任意節點左右子樹高度差絕對值≤1
  • 平衡因子(Balance Factor)
    合法取值范圍:{-1, 0, 1}

1.3 歷史背景

由前蘇聯科學家Adelson-Velsky和Landis于1962年提出,論文《An algorithm for the organization of information》首次描述這一數據結構。


2. 數據結構與節點定義

2.1 節點結構(C++實現)

template<class K, class V>
struct AVLTreeNode 
{std::pair<K, V> _kv;AVLTreeNode<K, V>* _left;   // 左子節點AVLTreeNode<K, V>* _right;  // 右子節點AVLTreeNode<K, V>* _parent; // 父節點(關鍵用于回溯更新)int _bf;                    // 平衡因子// 構造函數AVLTreeNode(const std::pair<K, V>& kv): _kv(kv), _left(nullptr), _right(nullptr),_parent(nullptr), _bf(0) {}
};

2.2 樹類框架

template<class K, class V>
class AVLTree 
{typedef AVLTreeNode<K, V> Node;
public:// 接口方法bool Insert(const std::pair<K, V>& kv);Node* Find(const K& key);// ...
private:Node* _root = nullptr;// 旋轉工具方法void RotateL(Node* parent);   // 左單旋void RotateR(Node* parent);   // 右單旋void RotateLR(Node* parent);  // 左右雙旋void RotateRL(Node* parent);  // 右左雙旋
};

3. 插入操作與平衡因子更新

3.1 插入流程

開始插入
根節點空?
創建新根節點
BST規則尋找插入位置
創建新節點并鏈接
回溯更新平衡因子
平衡因子是否失衡?
執行旋轉調整
結束插入

3.2 平衡因子更新規則

  • 插入右子樹:父節點bf++
  • 插入左子樹:父節點bf–
  • 更新終止條件
    1. bf == 0:子樹高度不變,停止更新
    2. bf == ±1:子樹高度變化,繼續向上回溯
    3. bf == ±2:觸發旋轉調整

3.3 關鍵代碼實現

bool Insert(const std::pair<K, V>& kv) {// ... BST插入邏輯//...// 平衡因子更新循環while (parent) {if (cur == parent->_left) parent->_bf--;else parent->_bf++;if (parent->_bf == 0) break;else if (abs(parent->_bf) == 1) {cur = parent;parent = parent->_parent;} else if (abs(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;}}return true;
}

4. 旋轉操作:從理論到代碼

4.1 右單旋(LL型失衡)

觸發條件
父節點bf = -2,左子節點bf = -1

代碼實現

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 (!ppNode) _root = subL;else if (ppNode->_left == parent) ppNode->_left = subL;else ppNode->_right = subL;subL->_parent = ppNode;// 更新平衡因子parent->_bf = subL->_bf = 0;
}

4.2 左單旋(RR型失衡)

觸發條件
父節點bf = 2,右子節點bf = 1

代碼實現

void RotateL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if(subRL)subRL->_parent = parent;Node* parentParent = parent->_parent;subR->_left = parent;parent->_parent = subR;if (parentParent == nullptr){_root = subR;subR->_parent = nullptr;}else{if (parent == parentParent->_left){parentParent->_left = subR;}else{parentParent->_right = subR;}subR->_parent = parentParent;}parent->_bf = subR->_bf = 0;
}

5. 雙旋場景深度剖析

5.1 左右雙旋(LR型失衡)

場景分析
當插入節點導致父節點bf=-2,且左子節點bf=1時,需要先對左子樹左旋,再對父節點右旋。

代碼實現

void RotateLR(Node* parent) 
{Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotateL(subL);RotateR(parent);// 平衡因子修正if (bf == 0) {parent->_bf = subL->_bf = 0;} else if (bf == -1) {parent->_bf = 1;subL->_bf = 0;} else {subL->_bf = -1;parent->_bf = 0;}subLR->_bf = 0;
}

5.2右左雙旋(RL型失衡)

情況與左右雙旋類似。

代碼實現:

void RotateRL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 0){subR->_bf = 0;subRL->_bf = 0;parent->_bf = 0;}else if (bf == 1){subR->_bf = 0;subRL->_bf = 0;parent->_bf = -1;}else if (bf == -1){subR->_bf = 1;subRL->_bf = 0;parent->_bf = 0;}else{assert(false);}
}

6. 平衡檢測與測試策略

6.1 遞歸驗證算法

bool IsBalance() {return _IsBalanceTree(_root);
}int _Height(Node* root) {if (!root) return 0;return 1 + std::max(_Height(root->_left), _Height(root->_right));
}bool _IsBalanceTree(Node* root) {if (!root) return true;int leftH = _Height(root->_left);int rightH = _Height(root->_right);if (rightH - leftH != root->_bf) {std::cout << "平衡因子異常:" << root->_kv.first;return false;}return abs(leftH - rightH) < 2 && _IsBalanceTree(root->_left)&& _IsBalanceTree(root->_right);
}

7. 性能分析與工程實踐

7.1 時間復雜度對比

操作BST最壞AVL樹紅黑樹
插入O(N)O(logN)O(logN)
刪除O(N)O(logN)O(logN)
查找O(N)O(logN)O(logN)

7.2 壓力測試

void StressTest() {AVLTree<int, int> tree;const int N = 1000000;// 隨機插入for (int i = 0; i < N; ++i) {tree.Insert({rand(), i});}assert(tree.IsBalance());// 查詢性能測試auto start = clock();for (int i = 0; i < N; ++i) {tree.Find(rand());}cout << "Query Time:" << clock() - start << "ms";
}

8. 總結

AVL樹的優勢

  • 嚴格的平衡保證最優查詢性能
  • 適合讀多寫少的場景

如有錯誤,懇請指正。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/82171.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/82171.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/82171.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

跨平臺游戲引擎 Axmol-2.6.0 發布

Axmol 2.6.0 版本是一個以錯誤修復和功能改進為主的次要LTS長期支持版本 &#x1f64f;感謝所有貢獻者及財務贊助者&#xff1a;scorewarrior、peterkharitonov、duong、thienphuoc、bingsoo、asnagni、paulocoutinhox、DelinWorks 相對于2.5.0版本的重要變更&#xff1a; 通…

【Django Serializer】一篇文章詳解 Django 序列化器

第一章 Django 序列化器概述 1.1 序列化器的定義 1.1.1 序列化與反序列化的概念 1. 序列化 想象你有一個裝滿各種物品&#xff08;數據對象&#xff09;的大箱子&#xff08;數據庫&#xff09;&#xff0c;但是你要把這些物品通過一個狹窄的管道&#xff08;網絡&#xff…

關于spring @Bean里調用其他產生bean的方法

背景 常常見到如下代碼 Bean public TestBean testBean() {TestBean t new TestBean();System.out.println("testBean:" t);return t; }Bean public FooBean fooBean() {TestBean t testBean();System.out.println("這里看似是自己new的&#xff0c;但因為…

Level1.7列表

1.7_1列表&#xff08;索引切片&#xff09; #1.列表 students[Bob,Alice,Jim,Mike,Judy] print(students)#2.在列表&#xff08;添加不同數據類型&#xff0c;查看列表是否可以運行&#xff1f;是否為列表類型&#xff1f;&#xff09; students[Bob,Alice,Jim,Mike,Judy,123…

Python爬蟲實戰:研究Cola框架相關技術

一、Cola 框架概述 Cola 是一款基于 Python 的異步爬蟲框架,專為高效抓取和處理大規模數據設計。它結合了 Scrapy 的強大功能和 asyncio 的異步性能優勢,特別適合需要高并發處理的爬蟲任務。 1.1 核心特性 異步 IO 支持:基于 asyncio 實現非阻塞 IO,大幅提高并發性能模塊…

vue2中el-table 實現前端分頁

一些接口不分頁的數據列表&#xff0c;一次性返回大量數據會導致前端渲染卡頓&#xff0c;接口不做分頁的情況下前端可以截取數據來做分頁 以下是一個例子&#xff0c;被截取的列表和全量數據在同一個棧內存空間&#xff0c;所以如果有表格內的表單編輯&#xff0c;新的值也會事…

Python + moviepy:根據圖片或數據高效生成視頻全流程詳解

前言 在數據可視化、自媒體內容生產、學術匯報等領域,我們常常需要將一組圖片或一段變動的數據,自動合成為視頻文件。這樣不僅能提升內容表現力,也極大節省了人工操作時間。Python作為數據處理和自動化領域的王者,其`moviepy`庫為我們提供了靈活高效的視頻生成方案。本文將…

科技賦能,開啟現代健康養生新潮流

在科技與生活深度融合的當下&#xff0c;健康養生也迎來了全新的打開方式。無需傳統醫學的介入&#xff0c;借助現代科學與智能設備&#xff0c;我們能以更高效、精準的方式守護健康。? 飲食管理步入精準化時代。利用手機上的營養計算 APP&#xff0c;錄入每日飲食&#xff0…

Ubuntu24.04 LTS安裝java8、mysql8.0

在 Ubuntu 24.04 上安裝 OpenJDK OpenJDK 包在 Ubuntu 24.04 的默認存儲庫中隨時可用。 打開終端并運行以下 apt 命令: sudo apt update查看是否已經安裝java java --version如果未安裝會有提示&#xff0c;直接復制命令安裝即可&#xff0c;默認版本&#xff1a; sudo apt in…

深度學習框架顯存泄漏診斷手冊(基于PyTorch的Memory Snapshot對比分析方法)

點擊 “AladdinEdu&#xff0c;同學們用得起的【H卡】算力平臺”&#xff0c;H卡級別算力&#xff0c;按量計費&#xff0c;靈活彈性&#xff0c;頂級配置&#xff0c;學生專屬優惠。 一、顯存泄漏&#xff1a;深度學習開發者的"隱形殺手" 在深度學習模型的訓練與推…

Pytorch分布式訓練,數據并行,單機多卡,多機多卡

分布式訓練 所有代碼可以見我github 倉庫&#xff1a;https://github.com/xiejialong/ddp_learning.git 數據并行&#xff08;Data Parallelism&#xff0c;DP&#xff09; 跨多個gpu訓練模型的最簡單方法是使用 torch.nn.DataParallel. 在這種方法中&#xff0c;模型被復制…

【論文閱讀】——D^3-Human: Dynamic Disentangled Digital Human from Monocular Vi

文章目錄 摘要1 引言2 相關工作3 方法3.1 HmSDF 表示3.2 區域聚合3.3. 變形場3.4. 遮擋感知可微分渲染3.5 訓練3.5.1 訓練策略3.5.2 重建損失3.5.3 正則化限制 4. 實驗4.1 定量評估4.2 定性評價4.3 消融研究4.4 應用程序 5 結論 摘要 我們介紹 D 3 D^{3} D3人&#xff0c;一種…

docker commit除了提交容器成鏡像,還能搞什么之修改cmd命令

要讓新鏡像默認啟動時執行 /usr/sbin/sshd -D&#xff0c;需在提交鏡像時 ??顯式指定新的啟動命令??。 方法一&#xff1a;提交時通過 --change 覆蓋 CMD docker commit --changeCMD ["/usr/sbin/sshd", "-D"] v2 project:v2 方法二&#xff1a;重…

為什么我輸入對了密碼,還是不能用 su 切換到 root?

“為什么我輸入對了密碼&#xff0c;還是不能用 su 切換到 root&#xff1f;” 其實這背后可能不是“密碼錯了”&#xff0c;而是系統不允許你用 su 切 root&#xff0c;即使密碼對了。 &#x1f447; 以下是最常見的幾個真正原因&#xff1a; ? 1. Root 用戶沒有設置密碼&…

轉移dp簡單數學數論

1.轉移dp問題 昨天的練習賽上有一個很好玩的起終點問題&#xff0c;第一時間給出bfs的寫法。 但是寫到后面發現不行&#xff0c;還得是的dp轉移的寫法才能完美的解決這道題目。 每個格子可以經過可以不經過&#xff0c;因此它的狀態空間是2^&#xff08;n*m&#xff09;&…

IP查詢基礎介紹

IP 查詢原理 IP 地址是網絡設備唯一標識&#xff0c;IP 查詢通過解析 IP 地址獲取地理位置、運營商等信息。目前主流的 IPv4&#xff08;32 位&#xff09;與 IPv6&#xff08;128 位&#xff09;協議&#xff0c;前者理論提供約 43 億地址&#xff0c;后者地址空間近乎無限。…

Linux命令簡介

1 Linux系統的命令概述 在 Linux 操作系統中&#xff0c;凡是在字符操作界面中輸入能夠完成特定操作和任務的字符串都可以稱為命令。嚴格來說&#xff0c;命令通常只代表實現某一類功能的指令或程序的名稱。 1.1 Shell Linux 命令的執行必須依賴于 Shell 命令解釋器。Shell …

WebRTC與RTSP|RTMP的技術對比:低延遲與穩定性如何決定音視頻直播的未來

引言 音視頻直播技術已經深刻影響了我們的生活方式&#xff0c;尤其是在教育、醫療、安防、娛樂等行業中&#xff0c;音視頻技術成為了行業發展的重要推動力。近年來&#xff0c;WebRTC作為一種開源的實時通信技術&#xff0c;成為了音視頻領域的重要選擇&#xff0c;它使得瀏覽…

多通道振弦式數據采集儀MCU安裝指南

設備介紹 數據采集儀 MCU集傳統數據采集器與5G/4G,LoRa/RS485兩種通信功能與一體的智能數據采集儀。該產品提供振弦、RS-485等的物理接口&#xff0c;能自動采集并存儲多種自然資源、建筑、橋梁、城市管廊、大壩、隧道、水利、氣象傳感器的實時數據&#xff0c;利用現場采集的數…

Vue3 + Element Plus表格篩選樣式設置

如果彈出框掛載在 body 下&#xff08;而非組件內部&#xff09;&#xff0c;scoped 樣式無法生效&#xff0c;這時就需要使用全局樣式。 強制全局樣式 1、添加全局樣式文件&#xff08;或在原有的文件中添加以下內容&#xff09; src/assets/global.scss /* 全局強制樣式覆…