C++模擬實現AVL樹

目錄

1.文章概括

2.AVL樹概念

3.AVL樹的性質

4.AVL樹的插入

5.旋轉控制

1.左單旋

2. 右單旋

3.左右雙旋

4.右左雙旋

6.全部代碼


1.文章概括

? ? ? ? 本文適合理解平衡二叉樹的讀者閱讀,因為AVL樹是平衡二叉樹的一種優化,其大部分實現邏輯與平衡二叉樹是相同的,相同的部分不做過多闡述。

2.AVL樹概念

? ? ? ? 平衡二叉樹主要用于查找數據,可提高查找效率,但如果數據有序或接近有序二叉搜索樹將退化為單支樹,查找元素相當于在順序表中搜索元素,效率低下。在這樣的缺點下,AVL樹被發明了出來。AVL樹的優化點在于:當向二叉搜索樹中插入新結點后,如果能保證每個結點的左右子樹高度之差的絕對值不超過1(需要對樹中的結點進行調整),即可降低樹的高度,從而減少平均搜索長度。

3.AVL樹的性質

? ? ? ? 一棵AVL樹或者是空樹,或者是具有以下性質的二叉搜索樹:

1.它的左右子樹都是AVL樹;

2.左右子樹高度之差(簡稱平衡因子)的絕對值不超過1(-1,0,1)。

AVL樹 == 高度平衡二叉搜索樹,說是平衡,為什么不是相等?

因為高度差不超過1,不是高度相等。

AVL樹圖片示例:

? ? ? ? 如此控制后,增刪改查的時間復雜度即為高度次 == O(logN)。

4.AVL樹的插入

????????對于一個結點的插入,分析如下:

1.新增在該結點的左,parent平衡因子減減;

2.新增在該結點的右,parent平衡因子加加;

3.更新后parent平衡因子 == 0,說明parent所在的子樹的高度不變,不會再影響祖先,不用再沿著到root的路徑往上更新;

4.更新后parent平衡因子 == 1 or -1,說明parent所在的子樹的高度變化,會再影響祖先,需要沿著到root的路徑往上更新;

5.更新后parent平衡因子 == 2 or -2,說明parent所在的子樹的高度變化且不平衡,對parent所在子樹進行旋轉,讓它平衡;

6.更到根結點。

補充說明:執行到4時會從1,2,開始繼續循環,執行到3,5,6時插入結束。

旋轉時需要注意的問題:

1.保持它是搜索樹;

2.變成平衡樹且降低這個子樹的高度。

代碼:

bool Insert(const T& data){Node* parent = nullptr;Node* cur = _pRoot;if (cur == nullptr){cur = new Node(data);_pRoot = cur;}while (cur){if (cur->_data > data){parent = cur;cur = cur->_pLeft;}else if (cur->_data < data){parent = cur;cur = cur->_pRight;}elsereturn false;}cur = new Node(data);if (parent->_data > data){parent->_pLeft = cur;cur->_pParent = parent;}else{parent->_pRight = cur;cur->_pParent = parent;}while (parent){if (parent->_pLeft == cur)parent->_bf--;elseparent->_bf++;if (parent->_bf == 0)return true;else if (parent->_bf == 1 || parent->_bf == -1){cur = parent;parent = parent->_pParent;}else{if (cur->_bf == 1 && parent->_bf == 2){RotateL(parent);}else if (cur->_bf == -1 && parent->_bf == -2){RotateR(parent);}else if (cur->_bf == -1 && parent->_bf == 2){RotateRL(parent);}else if (cur->_bf == 1 && parent->_bf == -2){RotateLR(parent);}break;}}}

? ? ? ? 代碼中,我使用了平衡因子來控制這棵樹的高度。

5.旋轉控制

1.左單旋

新節點插入較高右子樹的右側 --- 右右:

2. 右單旋

新節點插入較高左子樹的左側 --- 左左

3.左右雙旋

?新節點插入較高左子樹的右側---左右:

4.右左雙旋

新節點插入較高右子樹的左側 --- 右左:

6.全部代碼

#pragma once
#include <iostream>
#include <assert.h>
#include <vector>
using namespace std;template<class T>
struct AVLTreeNode
{AVLTreeNode(const T& data = T()): _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr), _data(data), _bf(0){}AVLTreeNode<T>* _pLeft;AVLTreeNode<T>* _pRight;AVLTreeNode<T>* _pParent;T _data;int _bf;   // 節點的平衡因子
};// AVL: 二叉搜索樹 + 平衡因子的限制
template<class T>
class AVLTree
{typedef AVLTreeNode<T> Node;
public:AVLTree(): _pRoot(nullptr){}// 在AVL樹中插入值為data的節點bool Insert(const T& data){Node* parent = nullptr;Node* cur = _pRoot;if (cur == nullptr){cur = new Node(data);_pRoot = cur;}while (cur){if (cur->_data > data){parent = cur;cur = cur->_pLeft;}else if (cur->_data < data){parent = cur;cur = cur->_pRight;}elsereturn false;}cur = new Node(data);if (parent->_data > data){parent->_pLeft = cur;cur->_pParent = parent;}else{parent->_pRight = cur;cur->_pParent = parent;}while (parent){if (parent->_pLeft == cur)parent->_bf--;elseparent->_bf++;if (parent->_bf == 0)return true;else if (parent->_bf == 1 || parent->_bf == -1){cur = parent;parent = parent->_pParent;}else{if (cur->_bf == 1 && parent->_bf == 2){RotateL(parent);}else if (cur->_bf == -1 && parent->_bf == -2){RotateR(parent);}else if (cur->_bf == -1 && parent->_bf == 2){RotateRL(parent);}else if (cur->_bf == 1 && parent->_bf == -2){RotateLR(parent);}break;}}}// AVL樹的驗證bool IsAVLTree(){return _IsAVLTree(_pRoot);}private:// 根據AVL樹的概念驗證pRoot是否為有效的AVL樹bool _IsAVLTree(Node* root){if (root == nullptr)return true;int leftHight = Height(root->_pLeft);int rightHight = Height(root->_pRight);if (rightHight - leftHight != root->_bf){cout << "平衡因子異常:" << root->_data << "->" << root->_bf << endl;return false;}return abs(rightHight - leftHight) < 2&& _IsAVLTree(root->_pLeft)&& _IsAVLTree(root->_pRight);}size_t Height(Node* root){if (root == nullptr)return 0;int leftHeight = Height(root->_pLeft);int rightHeight = Height(root->_pRight);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;}// 右單旋void RotateR(Node* pParent) {Node* cur = pParent->_pLeft;Node* curRight = cur->_pRight;Node* parentP = pParent->_pParent;pParent->_pLeft = curRight;if(curRight)curRight->_pParent = pParent;cur->_pRight = pParent;pParent->_pParent = cur;if (parentP == nullptr){_pRoot = cur;cur->_pParent = nullptr;}else{cur->_pParent = parentP;if (parentP->_pLeft == pParent)parentP->_pLeft = cur;elseparentP->_pRight = cur;}if(curRight)curRight->_bf = 0;pParent->_bf = cur->_bf = 0;}// 左單旋void RotateL(Node* pParent){Node* cur = pParent->_pRight;Node* curLeft = cur->_pLeft;Node* parentP = pParent->_pParent;pParent->_pRight = curLeft;if(curLeft)curLeft->_pParent = pParent;cur->_pLeft = pParent;pParent->_pParent = cur;if (parentP == nullptr){_pRoot = cur;cur->_pParent = nullptr;}else{cur->_pParent = parentP;if (parentP->_pLeft == pParent)parentP->_pLeft = cur;elseparentP->_pRight = cur;}if(curLeft)curLeft->_bf = 0;pParent->_bf = cur->_bf = 0;}// 右左雙旋void RotateRL(Node* pParent){Node* cur = pParent->_pRight;Node* curLeft = cur->_pLeft;int temp = curLeft->_bf;RotateR(cur);RotateL(pParent);if (temp == 0)return;else if (temp == 1){pParent->_bf = -1;cur->_bf = 0;curLeft->_bf = 0;}else if (temp == -1){pParent->_bf = 0;cur->_bf = 1;curLeft->_bf = 0;}elseassert(false);}// 左右雙旋void RotateLR(Node* pParent){Node* cur = pParent->_pLeft;Node* curRight = cur->_pRight;int temp = curRight->_bf;RotateL(cur);RotateR(pParent);if (temp == 0)return;else if (temp == 1){pParent->_bf = 0;cur->_bf = -1;curRight->_bf = 0;}else if (temp == -1){pParent->_bf = 1;cur->_bf = 0;curRight->_bf = 0;}elseassert(false);}private:Node* _pRoot;
};

??

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

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

相關文章

opc da 服務器數據 轉 EtherCAT項目案例

目錄 1 案例說明 2 VFBOX網關工作原理 3 應用條件 4 查看OPC DA服務器的相關參數 5 配置網關采集opc da數據 6 啟動EtherCAT從站轉發采集的數據 7 在服務器上運行仰科OPC DA采集軟件 8 案例總結 1 案例說明 在OPC DA服務器上運行OPC DA client軟件查看OPC DA服務器的相…

實驗9 基于WebGoat平臺的SQL注入攻擊

實驗9 基于WebGoat平臺的SQL注入攻擊 1.實驗目的 熟悉WebGoat平臺&#xff0c;在該平臺上實現SQL注入攻擊。 2.實驗內容 &#xff08;1&#xff09;下載webgoat-server-8.2.2.jar。 &#xff08;2&#xff09;搭建java環境。 &#xff08;3&#xff09;運行webgoat。 &#xf…

StochSync:可在任意空間中生成360°全景圖和3D網格紋理

StochSync方法可以用于在任意空間中生成圖像&#xff0c;尤其是360全景圖和3D網格紋理。該方法利用了預訓練的圖像擴散模型&#xff0c;以實現零-shot生成&#xff0c;消除了對新數據收集和單獨訓練生成模型的需求。StochSync 結合了 Diffusion Synchronization&#xff08;DS&…

研發管理知識

定義 研發管理是對研發活動進行有效的計劃、組織、領導和控制的過程&#xff0c;旨在通過合理配置資源、協調團隊工作、監控項目進度和質量等&#xff0c;確保研發項目能夠按時、按質、按量完成&#xff0c;實現企業的技術創新和產品升級目標&#xff0c;增強企業的核心競爭力。…

HarmonyOS 5.0應用開發——全局自定義彈出框openCustomDialog

【高心星出品】 文章目錄 全局自定義彈出框openCustomDialog案例開發步驟完整代碼 全局自定義彈出框openCustomDialog CustomDialog是自定義彈出框&#xff0c;可用于廣告、中獎、警告、軟件更新等與用戶交互響應操作。開發者可以通過CustomDialogController類顯示自定義彈出框…

AOS安裝及操作演示

文章目錄 一、安裝node1.1 在 macOS 上管理 Node版本1.1.1 安裝 nvm1.1.2 驗證 nvm 是否安裝成功1.1.3 使用 nvm 安裝/切換 Node.js 版本1.1.4 卸載 Node.js 版本 1.2 在 windows 上管理 Node版本1.2.1 安裝 nvm-windows1.2.2 安裝 Node.js 版本1.2.3 切換 Node.js 版本1.2.4 卸…

DeepSeek模型R1服務器繁忙,怎么解決?

在當今科技飛速發展的時代&#xff0c;人工智能領域不斷涌現出令人矚目的創新成果&#xff0c;其中DeepSeek模型無疑成為了眾多關注焦點。它憑借著先進的技術和卓越的性能&#xff0c;在行業內掀起了一股熱潮&#xff0c;吸引了無數目光。然而&#xff0c;如同許多前沿技術在發…

AIGC-微頭條爆款文案創作智能體完整指令(DeepSeek,豆包,千問,Kimi,GPT)

Unity3D特效百例案例項目實戰源碼Android-Unity實戰問題匯總游戲腳本-輔助自動化Android控件全解手冊再戰Android系列Scratch編程案例軟考全系列Unity3D學習專欄藍橋系列AIGC(GPT、DeepSeek、豆包、千問、Kimi)??關于作者 專注于Android/Unity和各種游戲開發技巧,以及各種資…

[LLM面試題] 指示微調(Prompt-tuning)與 Prefix-tuning區別

一、提示調整(Prompt Tuning) Prompt Tuning是一種通過改變輸入提示語&#xff08;input prompt&#xff09;以獲得更優模型效果的技術。舉個例子&#xff0c;如果我們想將一條英語句子翻譯成德語&#xff0c;可以采用多種不同的方式向模型提問&#xff0c;如下圖所示&#xf…

CSS 性能優化全攻略:提升網站加載速度與流暢度

系列文章目錄 01-從零開始學CSS選擇器&#xff1a;屬性選擇器與偽類選擇器完全指南 02-避免樣式沖突&#xff1a;掌握CSS選擇器優先級與層疊規則的終極指南 03-如何精確掌控網頁布局&#xff1f;深入解析 CSS 樣式與盒模型 04-CSS 布局全面解析&#xff1a;從傳統浮動到現代 F…

自主項目面試點總結

1、許苑–OJ判題系統 技術棧&#xff1a;Spring BootSpring Cloud AlibabaRedisMybatisMQDocker 項目地址: https://github.com/xuyuan-upward/xyoj-backend-microservice 1.1、項目介紹: 一個基于微服務的OJ系統&#xff0c;具備能夠根據管理員預設的題目用例對用戶提交的代…

12.推薦系統的前沿技術

接下來我們將學習推薦系統的前沿技術。推薦系統是一個快速發展的領域&#xff0c;許多新技術和新方法不斷涌現&#xff0c;進一步提升了推薦系統的性能和效果。在這一課中&#xff0c;我們將介紹以下內容&#xff1a; 圖神經網絡&#xff08;GNN&#xff09;在推薦系統中的應用…

【py】python安裝教程(Windows系統,python3.13.2版本為例)

1.下載地址 官網&#xff1a;https://www.python.org/ 官網下載地址&#xff1a;https://www.python.org/downloads/ 2.64版本或者32位選擇 【Stable Releases】&#xff1a;穩定發布版本&#xff0c;指的是已經測試過的版本&#xff0c;相對穩定。 【Pre-releases】&#…

CEF132 編譯指南 MacOS 篇 - depot_tools 安裝與配置 (四)

1. 引言 在 CEF132&#xff08;Chromium Embedded Framework&#xff09;的編譯過程中&#xff0c;depot_tools 扮演著舉足輕重的角色。這套由 Chromium 項目精心打造的腳本和工具集&#xff0c;專門用于獲取、管理和更新 Chromium 及其相關項目&#xff08;包括 CEF&#xff…

1312:【例3.4】昆蟲繁殖

1312&#xff1a;【例3.4】昆蟲繁殖 時間限制: 1000 ms 內存限制: 65536 KB 提交數:60386 通過數: 29787 【題目描述】 科學家在熱帶森林中發現了一種特殊的昆蟲&#xff0c;這種昆蟲的繁殖能力很強。每對成蟲過xx個月產yy對卵&#xff0c;每對卵要過兩個月長成成蟲…

Linux防火墻設置

目錄 Ubuntu防火墻&#xff08;UFW&#xff09;常用設置 1. 查看防火墻狀態 2. 開啟/關閉防火墻 3. 管理端口 4. 管理IP地址 5. 服務管理 CentOS防火墻&#xff08;firewalld&#xff09;常用設置 1. 查看防火墻狀態 2. 啟動/關閉防火墻 3. 設置開機啟動 4. 管理端口…

Git 日志查看與版本回溯

引言 在軟件開發的漫漫長路中&#xff0c;代碼就如同我們搭建軟件大廈的基石&#xff0c;而 Git 則是一位默默守護并精心管理這些基石的 “管家”。它不僅能記錄代碼的每一次變動&#xff0c;還提供了強大的日志查看和版本回溯功能&#xff0c;這些功能就像是給開發者配備了一…

針對Prompt優化的深入分析

一、針對Prompt優化的深入分析 1. 結構化設計 技術原理&#xff1a; 大語言模型&#xff08;LLMs&#xff09;本質是基于概率的序列生成器&#xff0c;結構化模板通過顯式定義輸出框架&#xff08;如角色、段落數、連接詞&#xff09;&#xff0c;利用模型的模式匹配能力&…

fps動作系統9:動畫音頻

文章目錄 動畫音頻創建音頻藍圖cue音量乘數 音效衰減衰減空間 綁定到動畫動畫序列軌道 動畫音頻 創建音頻藍圖 cue 音量乘數 音量大小 音效衰減 空間音效 衰減 空間 綁定到動畫 動畫序列 軌道 橫著的方向是有不同的軌道的&#xff0c;陰影的就是。

TensorRT【詳解】

文章目錄 1、 1、 參考&#xff1a; 1、nVidia TensorRT pytorch Docker 下載&#xff1a;https://catalog.ngc.nvidia.com/orgs/nvidia/containers/pytorch/tags 2、nVidia TensorRT pytorch Docker 版本講解&#xff1a;https://docs.nvidia.com/deeplearning/frameworks/py…