【數據結構 -- AVL樹】用golang實現AVL樹

目錄

  • 引言
  • 定義
  • 旋轉方式
    • LL型
    • RR型
    • LR型
    • RL型
  • 實現
    • 結構
    • 獲取結點高度
    • 平衡因子
    • 更新高度
    • 左旋
    • 右旋
    • 插入結點
    • 中序遍歷

引言

AVL樹,基于二叉搜索樹通過平衡得到

前面我們知道,通過🔗二叉搜索樹可以便捷快速地查找到數據,但是當序列有序時,就會退化成如下圖所示的單鏈表,搜索效率降低為O(N),為了解決這個問題,引出了平衡二叉樹(AVL樹)

在這里插入圖片描述

定義

平衡二叉樹,簡稱AVL樹,它可以是一顆空樹
如果不是空樹,則需要滿足 任何一個結點的左子樹與右子樹高度之差的絕對值不超過1

在這里插入圖片描述

圖一是AVL樹
圖二不是AVL樹,因為虛線內部分高度差大于1

如何讓二叉樹變成AVL樹呢
答案是通過旋轉(左旋、右旋)操作,在說左旋和右旋操作之前,了解一個概念——平衡因子

是否為AVL樹需要根據結點的左右子樹高度差來判斷,所以引出平衡因子的概念
平衡因子:結點左子樹高度減去右子樹高度
之后我們還可以通過平衡因子來判斷需要哪種旋轉方式(左旋、右旋)

將二叉樹分為四種類型,分別是LL(left)型、RR(right)型、
LR型、RL型
這幾種類型是根據引起不平衡的結點的位置來分的,下面將引起不平衡的這個結點叫做unbalanceNode

旋轉方式

判斷右旋還是左旋,可以這樣理解
向哪個方向旋轉就是讓哪邊樹更高。比如左旋,就是右子樹高于左子樹,要想平衡就要讓左子樹更高一點

LL型

unbalanceNode在根結點左孩子的左子樹 – 根結點右旋

如圖,插入結點5后導致二叉樹失衡,插入的結點5在根結點左孩子14的左子樹上,所以就是 LL 型

在這里插入圖片描述

LL型二叉樹的平衡因子滿足:
根結點:2
根結點的左孩子:1(左孩子的左子樹高度>右子樹)

方法就是將根結點右旋,意思就是將根結點向右旋轉到其左孩子的右孩子的位置

在這里插入圖片描述

在根結點向右旋轉的過程中,因為根結點的左孩子14原本有右孩子20,所以根結點就會和20發生沖突,這時需要將14的右孩子20變成根結點的左孩子

根結點25旋轉完成后就是

在這里插入圖片描述

再和14相連,最終結果:

在這里插入圖片描述


如果出現了多個結點都失衡的情況,如下圖
在這里插入圖片描述

46、35、24都失衡了,那這時候就不是將根結點右旋了,而是將 與導致失衡的結點(15)最近的失衡結點右旋,在這個例子中也就是將24右旋
在這里插入圖片描述

再與35相連,最終結果:
在這里插入圖片描述


RR型

unbalanceNode在根結點右孩子的右子樹 – 根結點左旋

RR 型與 LL 型方法一致,只是換湯不換藥

如圖,插入結點67后導致二叉樹失衡,插入的結點67在根結點右孩子45的右子樹上,所以就是 RR 型

在這里插入圖片描述

RR型二叉樹的平衡因子滿足:
根結點:-2
根結點的左孩子:-1(左孩子的右子樹高度>左子樹)

方法就是將根結點左旋,意思就是將根結點向左旋轉到其右孩子的左孩子的位置
在這里插入圖片描述

在根結點向左旋轉的過程中,因為根結點的右孩子45原本有左孩子34,所以根結點就會和34發生沖突,這時需要將45的左孩子34變成根結點的右孩子

根結點26旋轉完成后就是
在這里插入圖片描述

再和45相連,最終結果:
在這里插入圖片描述


如果同時出現了多個失衡結點,和 LL 型一樣,也是找到與導致失衡結點距離最近的失衡的結點,對該結點進行左旋操作


LR型

unbalanceNode在根結點左孩子的右子樹 – 先左旋再右旋(根結點的左孩子左旋,根結點右旋)

如圖,插入結點40后導致二叉樹失衡,插入的結點40在根結點左孩子25的右子樹上,所以就是 LR 型
在這里插入圖片描述

LR型的平衡因子滿足:
根結點:2
根結點的左孩子:-1(左孩子的右子樹高度>左子樹)

方法就是

  1. 先將根結點的左孩子左旋
  2. 再將根結點右旋

對于這個二叉樹,調整過程:

  1. 將根結點的左孩子左旋
    在這里插入圖片描述
  2. 將根結點右旋后
    在這里插入圖片描述

RL型

unbalanceNode在根結點右孩子的左子樹 – 先右旋再左旋(根結點的右孩子右旋,根結點左旋)

如圖,插入結點29后導致二叉樹失衡,插入的結點29在根結點右孩子48的左子樹上,所以就是 RL 型
在這里插入圖片描述

LR型的平衡因子滿足:
根結點:-2
根結點的右孩子:1(右孩子的左子樹高度>右子樹)

方法就是

  1. 先將根結點的右孩子右旋
  2. 再將根結點左旋

對于這個二叉樹,調整過程:

  1. 將根結點的右孩子右旋
    在這里插入圖片描述

  2. 將根結點左旋
    在這里插入圖片描述

實現

結構

結構體中一定包含的是數據data 和左右孩子指針
又因為需要計算平衡因子,所以需要知道左右子樹的高度,直接將高度height 包含在結構體中

// 定義樹結構
type BTNode struct {data   int //數據left   *BTNoderight  *BTNodeheight int //樹的高度
}

獲取結點高度

首先判斷結點 t 為不為 nil, 為 nil 直接返回0

// 獲取結點高度
func (t *BTNode) GetHeight() int {if t == nil {return 0}return t.height
}

平衡因子

平衡因子 = 左子樹高度 - 右子樹高度
若結點 t 為 nil ,直接返回0

// 計算結點的平衡因子 -- 左子樹高度-右子樹高度
func (t *BTNode) GetBalanceFactor() int {if t == nil {return 0}return t.left.GetHeight() - t.right.GetHeight()
}

更新高度

在插入或刪除數據后,根結點和其他結點的高度都有可能發生變化,所以在插入或刪除結點后,需要更新節點的高度,否則在計算平衡因子會出錯

// 更新高度
func (t *BTNode) UpdateHeight() {leftHeight := t.left.GetHeight()rightHeight := t.right.GetHeight()if leftHeight > rightHeight {t.height = leftHeight + 1} else {t.height = rightHeight + 1}
}

左旋

對 node 進行左旋 --> node連接在node.right 的左孩子,如果node.right 原本有左孩子leftChild,那讓leftChild 連接到node 的右孩子

// 左旋
func (t *BTNode) LeftRotate() *BTNode {//新的根結點變為t的右孩子newT := t.right//判斷newT有沒有左孩子if newT.left == nil{  //newT原本沒有左孩子,t為newt.T左孩子newT.left = t}else { //newT原本有左孩子,原本的左孩子變為t的右孩子,t為newT左孩子t.right = newT.leftnewT.left = t}//更新高度t.UpdateHeight()newT.UpdateHeight()return newT
}

對上面的代碼,還可以再簡化
如果newT沒有左孩子,即為nil,也可以直接賦值給t.right

// 左旋
func (t *BTNode) LeftRotate() *BTNode {//新的根結點變為t的右孩子newT := t.rightt.right = newT.leftnewT.left = t//更新高度t.UpdateHeight()newT.UpdateHeight()return newT
}

右旋

對 node 進行右旋 --> node連接在node.left 的右孩子,如果node.left 原本有右孩子rightChild,那讓rightChild 連接到node 的左孩子

// 右旋
func (t *BTNode) RightRotate() *BTNode {newT := t.leftt.left = newT.rightnewT.right = tt.UpdateHeight()newT.UpdateHeight()return newT
}

插入結點

按照二叉搜索樹插入數據的方式插入,再根據平衡因子判斷是否需要調整和調整的方式

// 插入結點
func (t *BTNode) Insert(data int) *BTNode {if t == nil {return &BTNode{data,nil,nil,1,}}//遞歸查找插入位置if data < t.data {t.left = t.left.Insert(data)} else if data > t.data {t.right = t.right.Insert(data)} else {return t //不支持重復數據}//更新當前結點的高度t.UpdateHeight()//檢查是否需要旋轉balance := t.GetBalanceFactor()//左子樹高if balance > 1 {if t.left.GetHeight() == 1 { //左孩子的左子樹高 -- ll型//右旋return t.RightRotate()}if t.left.GetHeight() == -1 { //左孩子的右子樹高 -- lr型//先對左孩子左旋,再對結點右旋t.left.LeftRotate()return t.RightRotate()}}//右子樹高if balance < -1 {if t.right.GetHeight() == 1 { //右孩子的右子樹高 -- rr型return t.LeftRotate()}if t.right.GetHeight() == -1 { //右孩子的左子樹高 -- rl型先對右孩子右旋,再對結點左旋t.right.RightRotate()return t.LeftRotate()}}return t
}

中序遍歷

// 中序遍歷
func (t *BTNode) InOrder() {if t == nil {return}t.left.InOrder()fmt.Printf("%d ", t.data)t.right.InOrder()
}

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

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

相關文章

PyTorch圖像識別模型和圖像分割模型體驗

文章目錄 倉庫地址練習&#xff1a;圖像自動識別模型數據集說明模型訓練和保存導入數據集搭建神經網絡訓練和保存實現 模型測試測試代碼測試結果 練習&#xff1a;圖像自動分割模型模型訓練和保存加載數據集搭建神經網絡訓練和保存 模型測試測試代碼測試效果 倉庫地址 圖像識別…

威綸通觸摸屏IP地址設定步驟及程序下載指南

在使用威綸通觸摸屏時&#xff0c;正確設定IP地址以及完成程序下載是確保其正常運行和實現功能的關鍵步驟。本文將詳細介紹威綸通觸摸屏IP地址設定步驟及程序下載的方法。 一、IP地址設定步驟 &#xff08;一&#xff09;前期準備 確保威綸通觸摸屏已經通電并啟動&#xff0…

一文讀懂|大模型智能體互操作協議:MCP/ACP/A2A/ANP

導讀 隨著推理大模型的出現&#xff08;deepseek&#xff0c;Qwen3等&#xff09;&#xff0c;進一步地推進了大模型的智能體系統發展。然而&#xff0c;如何使智能體更好的調用外部工具&#xff0c;智能體與智能體之間如何有機地協作&#xff0c;仍然沒有一個完美的答案。這篇…

前端下載ZIP包方法總結

在前端實現下載 ZIP 包到本地&#xff0c;通常有以下幾種方法&#xff0c;具體取決于 ZIP 包的來源&#xff08;靜態文件、后端生成、前端動態生成等&#xff09;&#xff1a; 方法 1&#xff1a;直接下載靜態文件&#xff08;最簡單&#xff09; 如果 ZIP 包是服務器上的靜態…

簡單使用Slidev和PPTist

簡單使用Slidev和PPTist 1 簡介 前端PPT制作有很多優秀的工具包&#xff0c;例如&#xff1a;Slidev、revealjs、PPTist等&#xff0c;Slidev對Markdown格式支持較好&#xff0c;適合與大模型結合使用&#xff0c;選喲二次封裝&#xff1b;revealjs適合做數據切換&#xff0c…

數據挖掘:從數據堆里“淘金”,你的數據價值被挖掘了嗎?

數據挖掘&#xff1a;從數據堆里“淘金”&#xff0c;你的數據價值被挖掘了嗎&#xff1f; 在這個數據爆炸的時代&#xff0c;我們每天都在產生海量信息&#xff1a;社交媒體上的點贊、網購時的瀏覽記錄&#xff0c;甚至是健身手環記錄下的步數。這些數據本身可能看似雜亂無章…

程序運行報錯分析文檔

zryhuawei:~/src/modules/Connect$ ./newbuild/OpConnectAidTool \WARNING: MYSQL_OPT_RECONNECT is deprecated and will be removed in a future version. replace into process_tracking (step_id,date,status,context_data,start_time,end_time,error_log) values(?,?,?…

基于flask+vue的電影可視化與智能推薦系統

基于flaskvue爬蟲的電影數據的智能推薦與可視化系統&#xff0c;能展示電影評分、評論情感分析等直觀的數據可視化圖表&#xff0c;還能通過協同過濾算法為用戶提供個性化電影推薦&#xff0c;幫助用戶發現更多感興趣的電影作品&#xff0c;具體界面如圖所示。 本系統主要技術架…

BYUCTF 2025

幾周沒會的比賽了&#xff0c;都是一題游。這周的BYU還不錯&#xff0c;難度適中&#xff0c;只是時間有點短。周末時間不夠。 Crypto Many Primes from Crypto.Util.number import bytes_to_long, getPrime import randomflag open("flag.txt").read().encode()…

鏈表的面試題8之環形鏈表

許久不見&#xff0c;那么這是最后倒數第三題了&#xff0c;這道題我們來看一下環形鏈表。 老規矩貼鏈接&#xff1a;141. 環形鏈表 - 力扣&#xff08;LeetCode&#xff09; 目錄 倒數第k個元素 獲取中間元素的問題。 雙指針 來&#xff0c;大致看一下題目&#xff0c;這…

在 JavaScript 中正確使用 Elasticsearch,第二部分

作者&#xff1a;來自 Elastic Jeffrey Rengifo 回顧生產環境中的最佳實踐&#xff0c;并講解如何在無服務器環境中運行 Elasticsearch Node.js 客戶端。 想獲得 Elastic 認證&#xff1f;查看下一期 Elasticsearch Engineer 培訓的時間&#xff01; Elasticsearch 擁有大量新…

2025年網站安全防御全解析:應對DDoS與CC攻擊的智能策略

2025年&#xff0c;隨著AI技術與物聯網設備的深度融合&#xff0c;DDoS與CC攻擊的規模與復雜度持續升級。攻擊者不僅利用T級流量洪泛沖擊帶寬&#xff0c;還通過生成式AI偽造用戶行為&#xff0c;繞過傳統防御規則。如何在保障業務高可用的同時抵御混合型攻擊&#xff1f;本文將…

window 安裝 wsl + cuda + Docker

WSL 部分參考這里安裝&#xff1a; Windows安裝WSL2 Ubuntu環境 - 知乎 如果出現錯誤&#xff1a; WslRegisterDistribution failed with error: 0x800701bc 需要運行&#xff1a;https://crayon-shin-chan.blog.csdn.net/article/details/122994190 wsl --update wsl --shu…

《MambaLLIE:基于隱式Retinex感知的低光照增強框架與全局-局部狀態空間建模》學習筆記

Paper:2405.16105 Github:GitHub - wengjiangwei/MambaLLIE 目錄 摘要 一、介紹 二、相關工作 2.1 低光圖像增強 2.2 視覺空間狀態模型 三、方法 3.1 預備知識 3.2 整體流程 3.3 全局優先-局部次之狀態空間塊 四、實驗 4.1 基準數據集與實施細節 4.2 對比實驗 4…

微信小程序:封裝request請求、解決請求路徑問題

一、創建文件 1、創建請求文件 創建工具類文件request.js,目的是用于發送請求 二、js接口封裝 1、寫入接口路徑 創建一個變量BASE_URL專門存儲api請求地址 2、獲取全局的token變量 從緩存中取出token的數據 3、執行請求 (1)方法中接收傳遞的參數 function request(url,…

【單機版OCR】清華TH-OCR v9.0免費版

今天向大家介紹一款非常好用的單機版OCR圖文識別軟件&#xff0c;它不僅功能多&#xff0c;識別能力強&#xff0c;而且還是免費使用的。OCR軟件為什么要使用單機版&#xff0c;懂得都懂&#xff0c;因為如果使用在線識別的OCR軟件&#xff0c;用戶需要將文檔上傳互聯網服務器的…

開源情報搜集系統:科研創新的強大引擎

一、引言 在當今全球化和信息化高度發展的時代&#xff0c;科研活動面臨著前所未有的機遇與挑戰。一方面&#xff0c;知識的更新換代速度極快&#xff0c;科研成果如雨后春筍般不斷涌現&#xff1b;另一方面&#xff0c;科研競爭日益激烈&#xff0c;如何在眾多科研團隊中脫穎…

產品生命周期不同階段的營銷策略

產品生命周期的不同階段&#xff08;導入期、成長期、成熟期、衰退期&#xff09;需要匹配差異化的營銷策略。以下是各階段的營銷重點及具體策略&#xff1a; 1. 導入期&#xff08;Introduction Stage&#xff09; 核心目標&#xff1a;建立市場認知&#xff0c;快速觸達目標…

Mujoco 學習系列(二)基礎功能與xml使用

這篇文章是 Mujoco 學習系列第二篇&#xff0c;主要介紹一些基礎功能與 xmI 使用&#xff0c;重點在于如何編寫與讀懂 xml 文件。 運行這篇博客前請先確保正確安裝 Mujoco 并通過了基本功能與GUI的驗證&#xff0c;即至少完整下面這個博客的 第二章節 內容&#xff1a; Mujoc…

面向SDV的在環測試深度解析——仿真中間件SIL KIT應用篇

1.引言 在汽車行業向軟件定義汽車&#xff08;SDV&#xff09;轉型的過程中&#xff0c;傳統硬件在環&#xff08;HIL&#xff09;測試方案因難以適應新的技術架構與需求&#xff0c;其局限性日益凸顯。傳統HIL對硬件依賴性強&#xff0c;擴展性差&#xff0c;更換ECU或傳感器…