數據結構之紅黑樹(還在爲看不懂紅黑樹而煩惱嗎?別再翻了,此篇足矣~)

  紅黑樹,非常經典的數據結構,主要用於一些容器中,比如C++語言中的mapJava語言中的TreeMap(後面會寫源碼分析博客)。紅黑樹能保持高效的查找,一般取時間複雜度爲O(log2n),由於高效,這個結構也比較複雜,所以很多人(包括我自己)都一直搞不懂紅黑樹到底是怎麼插入刪除節點的。此篇博客,博主將圖文並茂的一層一層揭開紅黑樹神祕面紗。

  \color{red}溫馨提示:要徹底搞懂紅黑樹,難度還是比較大的,建議先閱讀我之前寫的兩篇博客做鋪墊,數據結構之二叉樹、AVL樹、紅黑樹、Trie樹、B樹、B+樹、B*樹淺析數據結構之二叉搜索樹詳解(附C++代碼實現查找、插入、刪除操作)。前者是通識篇,主要介紹了幾種樹結構的區別,後者單獨介紹二叉搜索樹插入、刪除操作。(其實紅黑樹 = 二叉搜索樹 + 弱平衡

一、紅黑樹概述

1、什麼是紅黑樹

  紅黑樹是一棵二叉搜索樹,並且這棵樹實現了弱平衡(嚴格的平衡是對於樹中任意節點的左右子樹高度差不超過1)。弱平衡是指任意節點到到其子樹中的葉節點所經過的黑色節點數相同,也可以稱爲黑色平衡(因爲嚴格平衡的二叉搜索樹AVL,維護成本太高,所以退而求其次)。
在這裏插入圖片描述

2、紅黑樹的五大特性

  紅黑樹的五大特性:

1、節點是紅色或者是黑色
2、根節點是黑色
3、每個葉節點(NIL或空節點)是黑色
4、每個紅色節點的兩個子節點都是黑色的
5、任意節點到其子樹中的葉節點所經過的黑色節點數相同(黑高相同)

  \color{red}注:紅黑樹引入了NIL節點,用於填充節點的左或右爲空的位置,因此紅黑樹中的葉節點特指NIL節點。
  一說定義,博客的畫風瞬間變得枯燥起來了,可能有些小夥伴已經開始有牴觸情緒的。這些特徵你可以不用記住,後面用到的時候我會反覆提出來的。

3、爲什麼要引入紅黑樹

  還記不記得在博客 數據結構之二叉搜索樹詳解(附C++代碼實現查找、插入、刪除操作) 中使用二叉搜索樹遇到的插入有序遞增序列退化成鏈表的缺陷。
在這裏插入圖片描述
  如果不引入平衡的概念,這種普通的二叉搜索樹的效率將大大降低。但是引入強平衡(樹中任意節點的左右子樹高度差不超過1),形如AVL樹,樹的維護成本太高。爲此Rudolf Bayer發明了一種帶顏色標記的二叉搜索樹即紅黑樹,此樹弱平衡,任意節點到其子樹中的葉節點所經過的黑色節點數相同。

二、紅黑樹相關操作

  紅黑樹看起來挺簡單的,不就是給每個節點都表上顏色麼。但是實際維護還是比較複雜的,比如刪除了一個節點如何調整?新增了一個節點表什麼顏色?插入後樹要進行怎樣的調整?

1、節點旋轉

  爲了調整紅黑樹的平衡,引入了兩種旋轉操作。具體過程請看圖。

①、左旋

  左旋,將旋轉節點B放到它的父節點A的位置,將父節點A置爲旋轉節點B的左子樹,然後將旋轉節點B的左子樹放到父節點A的右子節點位置。
在這裏插入圖片描述

②、右旋

  右旋,將旋轉節點B放到它的父節點A的位置,將父節點A置爲旋轉節點B的右子樹,然後將旋轉節點B的右子樹放到父節點A的左子節點位置。
在這裏插入圖片描述

2、查找節點

  查找節點紅黑樹三大操作中最爲簡單的操作,因爲紅黑樹是一棵特殊的二叉搜索樹,所以按照二叉搜索樹的查找方式查找即可。查找僞代碼:

root 紅黑樹根,target 需要查找的value
while root != NULL
	if root->value == target
		// 查找成功
		break
	else if root->value > target
		// 二叉搜索樹 左子樹任意節點.value < 根.value < 右子樹任意節點.value
		// 根.value > target,則target只可能存在左子樹中
		root = root->left
	else
		// 二叉搜索樹 左子樹任意節點.value < 根.value < 右子樹任意節點.value
		// 根.value < target,則target只可能存在右子樹中
		root = root->right
// root == NULL,則說明未找到
return root

  紅黑樹中元素查找示例圖解:
在這裏插入圖片描述

3、插入節點

  紅黑樹中插入節點是稍微複雜一點點的操作,請保證前面的都消化完畢再繼續閱讀。

4、刪除節點

三、總結

...\color{red}未完待續...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章