平衡二叉樹

AVL簡稱平衡二叉樹,縮寫為BBST,由蘇聯數學家 Adelse-Velskil 和 Landis 在 1962 年提出。

二叉樹是動態查找的典范,但在極限情況下,二叉樹的查找效果等同于鏈表,而平衡二叉樹可以完美的達到 log ? 2 n \log_2 n log2?n

一直想深入的研究一下,并手寫平衡二叉樹的插入、刪除代碼。

可惜的是,國內數據結構的神級教材:閻蔚敏老師主編《數據結構》一書中并未看到關于AVL樹的代碼。

例子:

將17,9,2,12,14,26,33,15,40,23,25一次插入到一棵初始化為空的AVL樹中,畫出該二叉平衡樹。

解:過程和結果如下圖所示。

在這里插入圖片描述

所謂平衡二叉樹,就是指二叉樹的左、右子樹的深度差不超過2。每當插入一個新的元素,導致左右子樹的深度超過2層時,需要對二叉樹的失衡節點進行平衡,保持左右子樹高度差在-1到1之間。

可以使用兩個整數來表示左右子樹的深度,前面一個表示左子樹的層數,右邊一個代表右子樹的層數。

調整時,首先需要找到要平衡的節點。找到調整節點后,處理的方法有4種:

上圖中圓標號1的是左-左結構,標號2的是左-右結構,標號3的是右-右,標號4的是右-左結構,這4種結構的處理方式各有不同。

  1. 左-左結構,即(2,1)結構

中間節點當作父節點,最上面的節點當作右節點,最下邊節點當作左節點

  1. 左-右結構,即(2,-1)結構

最下面節點當作父節點,父節點當作右節點,中間節點當作左節點

  1. 右-右結構,即(-2,-1)結構

中間節點當作父節點,最上面的節點當作左節點,最下邊節點當作右節點

  1. 右-左結構,即(-2,1)結構

最下面節點當作父節點,最上面節點當作左節點,中間節點當作右節點

編程中,計算左、右子樹深度的代碼如下:


int deep(BBST* b) {if (b == 0){return 0;}int ld =  deep(b->lchild);int rd = deep(b->rchild) ;return ld > rd ? ld + 1 : rd + 1;
}

有了上面的理論和編程基礎,我們可以慢慢的調試并手動寫出平衡二叉樹的插入代碼:

int BBSTree::insert(ELEMENT* e) {if (mTree == 0){mTree = newnode(e);mSize = 1;return 1;}BBST* t = mTree;BBST* tc = 0;Stack s;ELEMENT elem;while (1) {if (e->e == t->data.e) {return 0;}else if (e->e > t->data.e){if (t->rchild == 0){tc = newnode(e);tc->parent = t;t->rchild = tc;mSize++;break;}else {			elem.e = (unsigned long long)t;s.push((ELEMENT*)&elem);t = t->rchild;				}}else {if (t->lchild == 0){tc = newnode(e);tc->parent = t;t->lchild = tc;mSize++;break;}else {elem.e = (unsigned long long)t;s.push((ELEMENT*)&elem);t = t->lchild;		}}}while (s.isEmpty() == 0) {s.pop(&elem);BBST* b = (BBST*)elem.e;b->ld = deep(b->lchild);b->rd = deep(b->rchild);t->ld = deep(t->lchild);t->rd = deep(t->rchild);int high_diff = b->ld - b->rd;int low_diff = t->ld - t->rd;if(high_diff == 2 && low_diff == 1){BBST* f = (BBST*)b->parent;if (f&&f->lchild == b){f->lchild = t;}else if (f&&f->rchild == b){f->rchild = t;}t->parent = f;BBST* tr = t->rchild;t->rchild = b;b->parent = t;b->lchild = tr;if (tr){tr->parent = b;}if (b == mTree){mTree = t;}}else if (high_diff == 2 && low_diff == -1){BBST* f = (BBST*)b->parent;if (f->lchild == b){f->lchild = tc;}else if (f->rchild == b){f->rchild = tc;}tc->parent = f;t->parent = tc;if (tc->lchild){tc->lchild->parent = t;}t->rchild = tc->lchild;b->parent = tc;if (tc->rchild){tc->rchild->parent = b;}b->lchild = tc->rchild;tc->rchild = b;tc->lchild = t;		if (b == mTree){mTree = tc;}}else if (high_diff == -2 && low_diff == 1){BBST* f = (BBST*)b->parent;if (f&&f->lchild == b){f->lchild = tc;}else if (f&&f->rchild == b){f->rchild = tc;}tc->parent = f;b->parent = tc;b->rchild = tc->lchild;if (tc->lchild){tc->lchild->parent = b;}t->parent = tc;t->lchild = tc->rchild;if (tc->rchild){tc->rchild->parent = t;}tc->rchild = t;tc->lchild = b;if (b == mTree){mTree = tc;}}else if (high_diff == -2 && low_diff == -1){BBST* f = (BBST*)b->parent;if (f && f->lchild == b){f->lchild = t;}else if (f && f->rchild == b){f->rchild = t;}t->parent = f;BBST* tl = t->lchild;t->lchild = b;b->parent = t;b->rchild = tl;if (tl){tl->parent = b;}if (b == mTree){mTree = t;}}tc = t;t = b;}return 0;
}

完整代碼地址:
https://github.com/satadriver/dataStruct

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

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

相關文章

ElementPlus table 中嵌套 input 輸入框

文章目錄 需求分析 需求 vue3 項目中 使用UI組件庫 ElementPlus 時&#xff0c;table 中嵌入 input輸入框 分析 <template><div class"p-10"><el-table :data"tableData" border><el-table-column prop"date" label&qu…

課堂練習4.1:段式內存管理

4-1 課堂練習4.1&#xff1a;段式內存管理 段式內存管理以段為單位分配內存空間&#xff0c;段內連續&#xff0c;段間可以不連續。段可以很大&#xff0c;比如數據段、代碼段、棧段等。本實訓分析 Linux 0.11 的段式內存管理技術。 第1關1 號進程 mynext 變量的邏輯地址與線性…

cache教程 3.HTTP服務器

上一節我們實現了單機版的緩存服務&#xff0c;但是我們的目標是分布式緩存。那么&#xff0c;我們就需要把緩存服務部署到多態機器節點上&#xff0c;對外提供訪問接口。客戶端就可以通過這些接口去實現緩存的增刪改查。 分布式緩存需要實現節點間通信&#xff0c;而通信方法…

【面試經典150 | 二叉樹】翻轉二叉樹

文章目錄 寫在前面Tag題目來源題目解讀解題思路方法一&#xff1a;遞歸方法二&#xff1a;迭代 寫在最后 寫在前面 本專欄專注于分析與講解【面試經典150】算法&#xff0c;兩到三天更新一篇文章&#xff0c;歡迎催更…… 專欄內容以分析題目為主&#xff0c;并附帶一些對于本題…

4-SpringMVC

文章目錄 項目源碼地址回顧-MVC什么是MVC&#xff1f;MVC各部分組成 回顧-ServletMaven創建Web項目1、創建Maven父工程pom&#xff0c;并導入依賴2、用Maven新建一個Web Module3、代碼&#xff1a;HelloServlet.java3、代碼-hello.jsp3、代碼-web.xml4、配置Tomcat5、瀏覽器測試…

github使用方法【附安裝包】

如果你是一枚Coder&#xff0c;但是你不知道Github&#xff0c;那么我覺的你就不是一個菜鳥級別的Coder&#xff0c;因為你壓根不是真正Coder&#xff0c;你只是一個Code搬運工。說明你根本不善于突破自己&#xff01;為什么這么說原因很簡單&#xff0c;很多優秀的代碼以及各種…

高級系統架構設計師之路

前言&#xff1a;系 統 架 構 設 計 師 (System Architecture Designer)是項目開發活動中的眾多角色之 一 &#xff0c;它可 以是 一個人或 一個小組&#xff0c;也可以是一個團隊。架構師 (Architect) 包含建筑師、設計師、創造 者、締造者等含義&#xff0c;可以說&#xff0…

邊緣計算系統設計與實踐:引領科技創新的新浪潮

文章目錄 一、邊緣計算的概念二、邊緣計算的設計原則三、邊緣計算的關鍵技術四、邊緣計算的實踐應用《邊緣計算系統設計與實踐》特色內容簡介作者簡介目錄前言/序言本書讀者對象獲取方式 隨著物聯網、大數據和人工智能等技術的快速發展&#xff0c;傳統的中心化計算模式已經無法…

基于ssm人力資源管理系統論文

摘 要 隨著企業員工人數的不斷增多&#xff0c;企業在人力資源管理方面負擔越來越重&#xff0c;因此&#xff0c;為提高企業人力資源管理效率&#xff0c;特開發了本人力資源管理系統。 本文重點闡述了人力資源管理系統的開發過程&#xff0c;以實際運用為開發背景&#xff0…

【大數據】Hudi 核心知識點詳解(一)

Hudi 核心知識點詳解&#xff08;一&#xff09; 1.數據湖與數據倉庫的區別 &#xff1f;1.1 數據倉庫1.2 數據湖1.3 兩者的區別 2.Hudi 基礎功能2.1 Hudi 簡介2.2 Hudi 功能2.3 Hudi 的特性2.4 Hudi 的架構2.5 湖倉一體架構 3.Hudi 數據管理3.1 Hudi 表數據結構3.1.1 .hoodie …

【C語言】位運算實現二進制數據處理及BCD碼轉換

文章目錄 1&#xff0e;編程實驗&#xff1a;按short和unsigned short類型分別對-12345進行左移2位和右移2位操作&#xff0c;并輸出結果。2&#xff0e;編程實驗&#xff1a;利用位運算實現BCD碼與十進制數之間的轉換&#xff0c;假設數據類型為unsigned char。3&#xff0e;編…

FPGA | Verilog基礎語法

這里寫自定義目錄標題 Case語句系統任務$dumpfile | 為所要創建的VCD文件指定文件名。$dumpvar | 指定需要記錄到VCD文件中的信號$fscanf$fread菜鳥教程連接 Case語句 case(case_expr)condition1 : true_statement1 ;condition2 : true_stat…

多線程(進階二:CAS)

目錄 一、CAS的簡單介紹 CAS邏輯&#xff08;用偽代碼來描述&#xff09; 二、CAS在多線程中簡單的使用 三、原子類自增的代碼分析 都看到這了&#xff0c;點個贊再走吧&#xff0c;謝謝謝謝謝 一、CAS的簡單介紹 CAS的全稱&#xff1a;“Compare And Swap”&#xff0c;字…

C語言——字符函數和字符串函數(一)

&#x1f4dd;前言&#xff1a; 這篇文章對我最近學習的有關字符串的函數做一個總結和整理&#xff0c;主要講解字符函數和字符串函數&#xff08;strlen&#xff0c;strcpy和strncpy&#xff0c;strcat和strncat&#xff09;的使用方法&#xff0c;使用場景和一些注意事項&…

python常見庫的匯總

python常見庫 一、爬蟲二、界面開發三、圖片處理四、視頻處理、視頻剪輯五、音頻處理六、數據處理七、數據庫八、網頁開發九、神經學習、AI開發十、打包十一、Excel處理十二、微信十三、控制鼠標鍵盤十四、手柄十五、控制外設十六、郵箱十七、短信 一、爬蟲 Requests&#xff…

Java入門項目--螞蟻愛購

簡介 這是一個靠譜的Java入門項目實戰&#xff0c;名字叫螞蟻愛購。 從零開發項目&#xff0c;視頻加文檔&#xff0c;十天就能學會開發JavaWeb項目&#xff0c;教程路線是&#xff1a;搭建環境> 安裝軟件> 創建項目> 添加依賴和配置> 通過表生成代碼> 編寫Ja…

解鎖MySQL的威力:針對常見問題的快速解決指南

數據庫和表的創建 創建數據庫&#xff1a; CREATE DATABASE IF NOT EXISTS MyDatabase; USE MyDatabase;案例&#xff1a; 想象您要開始一個博客項目。首先&#xff0c;您需要一個地方來存儲所有的文章和用戶信息。上述命令幫助您創建了這樣一個存儲空間&#xff0c;名為MyDa…

Tomcat使用https方式連接

Tomcat使用https方式連接 攏共分兩步&#xff0c;第一步&#xff1a;生成密鑰。第二步&#xff1a;修改配置。 第一步&#xff1a;生成密鑰。 keytool -genkey -v -alias tomcat -keyalg RSA -validity 365 -keystore /usr/tomcat-8.5/conf/tomcat.keystore第二步&#xff1…

RocketMQ-源碼架構二

梳理一些比較完整&#xff0c;比較復雜的業務線 消息持久化設計 RocketMQ的持久化文件結構 消息持久化也就是將內存中的消息寫入到本地磁盤的過程。而磁盤IO操作通常是一個很耗性能&#xff0c;很慢的操作&#xff0c;所以&#xff0c;對消息持久化機制的設計&#xff0c;是…

華為機試真題 C++ 實現【字符串重新排列】

題目 給定一個字符串s&#xff0c;s包括以空格分隔的若干個單詞&#xff0c;請對s進行如下處理后輸出&#xff1a; 1、單詞內部調整&#xff1a;對每個單詞字母重新按字典序排序 2、單詞間順序調整&#xff1a; 1&#xff09;統計每個單詞出現的次數&#xff0c;并按次數降序…