【一份程式碼搞定資料結構】紅黑樹(更新中)
在介紹紅黑樹之前先說明什麼是二叉查詢樹和平衡二叉樹。
一、二叉查詢樹(BST)
1 . 二叉查詢樹本身就是一個空樹。
2 . 左子樹的數值 < 根節點 < 右子樹的數值。
基本四個操作:查詢 , 插入 , 建樹 , 刪除。由於不是重點要說明的,所以只是貼出來用一下。
#include<iostream>
using namespace std;
struct node{
int data;
node* lchild;
node* rchild;
};
node* newNode(int x){
node* Node = new node;
Node->data = x;
Node->lchild = NULL:
Node->rchild = NULL;
return Node;
}
void search(node* root , int x){
//根節點的數值//
if(root == NULL){
printf("search failed!\n");
return ;
}
//找到的話//
if(x == root->data){
printf("%d\n" , root->data);
}
//比它小,往左走//
else if(x < root->data){
search(root->lchild , x);
}
//比它大 ,往右走//
else{
search(root->rchild , x);
}
}
//插入操作//
void insert(node* root , int x){
if(root == NULL){
root = newNode(x);
return ;
}
if(x == root->data){
return ;
}
else if(x < root->lchild){
insert(root->lchild , x);
}
else{
insert(root->rchild , x);
}
}
//輔助刪除函式,用於找一個數值的節點//
node* findMax(node* root){
while(root->rchild != NULL){
root = root->rchild;
}
return ;
}
node* findMin(node* root){
while(root->lchild != NULL){
root = root->lchild;
}
return ;
}
void deleteNode(node* &root , int x){
//範圍//
if(root == NULL){
return ;
}
//當輸入的數值和要刪除的數值是一樣的話//
if(root->data == x){
//本身數值沒有左右子節點,放空即可//
if(root->lchild == NULL && root->rchild == NULL){
root = NULL;
}
//如果左結點不空的時候//
else if(root->lchild != NULL){
//刪除結點的數值//
node* pre = findMax(root->lchild);
root->data = pre->data;
deleteNode(root->lchild , pre->data);
}
//如果右結點不空的時候//
else{
node* next = findMin(root->rchild);
root->data = next->data;
deleteNode(root->rchild , next->data);
}
//如果找的左右節點的數值不一樣的話,接著找.//
else if(root->data > x){
deleteNode(root->lchild , x);
}
else{
deleteNode(root->rchild , x);
}
}
二、平衡二叉樹(AVL)
平衡二叉樹最關鍵的一點就是結點的平衡因子。所謂平衡因子就是左子樹的數值和右子樹的高度差。當每個結點的平衡因子的數值的決定不超過1的時候,即為平衡二叉樹。
基本操作幾乎一致,主要是旋轉註意一下。
#include<iostream>
using namespace std;
struct node{
int v ;
int height;//當前結點高度//
node* lchild;
node* rchild;
};
//建立結點//
node* newNode(int v){
node* Node = new node;
Node->v = v;
Node->height = 1;
Node->rchild = NULL;
Node->lchild = NULL;
return Node;
}
//結點高度函式//
int getheight(node* root){
//結點為空//
if(root == NULL)
return 0;
return root->height;
}
//平衡因子的計算//
int getBalance(node* root){
return getheight(root->lchild) - getheight(root->rchild);
}
//更新結點的高度//
void updateheight(node *root){
root->height = max(getheight(root->lchild) , getheight(root->rchild) + 1);
}
//查詢操作//
void search(node* root ,int x){
if(root == NULL){
printf("search Falled!\n");
return ;
}
//找到即輸出//
if(x == root->v){
printf("%d\n" , root->v);
}
//類似二叉搜尋樹查詢//
else if(x < root->v){
search(root->lchild , x);
}
else{
search(root->rchild , x);
}
}
//左旋//
void L(node* &root){
node *temp = root->rchild;
root->rchild = temp->rchild;
temp->lchild = root;
updateheight(root);
updateheight(temp);
root = temp;
}
//右旋//
void R(node* &root){
node *temp = root->lchild;
root->lchild = temp->lchild;
temp->rchild = root;
updateheight(root);
updateheight(temp);
root = temp;
}
void insert(node* &root , int x){
if(root == NULL){
root = newNode(x);
return ;
}
//類似平衡二叉樹的插入演算法 , 加了一點東西//
if(x < root->v){
insert(root->lchild , x);
//更新高度//
updateheight(root);
if(getBalance(root) == 2){
if(getBalance(root->lchild) == 1){
R(root);
}
else if(getBalance(root->rchild) == -1){
L(root->lchild);
R(root);
}
}
}
else{
insert(root->rchild , x);
updateheight(root);
if(getBalance(root) == -2){
if(getBalance(root->lchild) == -1){
L(root);
}
else if(getBalance(root->rchild) == 1){
R(root->rchild);
L(root);
}
}
}
}
//新建二叉樹//
node* creat(int data[] , int n){
node* root = NULL;
//迴圈插入//
for(int i = 0 ; i < n ; i ++) {
insert(root , data[i]);
}
return root;
}
三、最終進化 -- 紅黑樹(RBT)
紅黑樹的起源,自然是二叉查詢樹。這種樹結構從根節點開始,左子節點小於它,右子節點大於它。每個節點都符合這個特性,所以易於查詢,是一種很好的資料結構。但是它有一個問題,就是容易偏向某一側,這樣就像一個連結串列結構了,失去了樹結構的優點,查詢時間會變壞, 在這種需求下,平衡樹的概念就應運而生了。
紅黑樹的用途:
- STL(標準模板庫)中在set map是基於紅黑樹實現的。
- Java中在TreeMap使用的也是紅黑樹。
- epoll在核心中的實現,用紅黑樹管理事件塊。
- linux程式排程Completely Fair Scheduler,用紅黑樹管理程式控制塊
紅黑樹與他們的前輩們的比較:
-
從實現細節上來講,如果插入一個結點引起了樹的不平衡,AVL樹和紅黑樹都最多需要2次旋轉操作,即兩者都是O(1);但是在刪除node引起樹的不平衡時,最壞情況下,AVL需要維護從被刪node到root這條路徑上所有node的平衡性,因此需要旋轉的量級O(logN),而RB-Tree最多隻需3次旋轉,只需要O(1)的複雜度。
-
從兩種平衡樹對平衡的要求來講,AVL的結構相較RB-Tree來說更為平衡,在插入和刪除node更容易引起Tree的unbalance,因此在大量資料需要插入或者刪除時,AVL需要rebalance的頻率會更高。因此,RB-Tree在需要大量插入和刪除node的場景下,效率更高。自然,由於AVL高度平衡,因此AVL的search效率更高。
紅黑樹的基本的特點:
- 根是黑色。
- 所有葉子都是黑色(葉子是NIL結點)。
- 每個紅色結點必須有兩個黑色的子結點。(從每個葉子到根的所有路徑上不能有兩個連續的紅色結點。)
- 從任一結點到其每個葉子的所有簡單路徑都包含相同數目的黑色結點。
- http://www.cnblogs.com/skywang12345/p/3624202.html
- https://www.sohu.com/a/201923614_466939
相關文章
- 資料結構--紅黑樹資料結構
- 資料結構之「紅黑樹」資料結構
- 資料結構基礎03-紅黑樹資料結構
- 演算法與資料結構--簡析紅黑樹演算法資料結構
- 【資料結構與演算法】手撕紅黑樹資料結構演算法
- 資料結構與演算法(十三)——紅黑樹2資料結構演算法
- 資料結構與演算法(十三)——紅黑樹1資料結構演算法
- 資料結構和演算法-二叉樹,AVL,紅黑樹資料結構演算法二叉樹
- 紅黑樹核心程式碼分析(JAVA)Java
- 資料結構和演算法學習筆記十六:紅黑樹資料結構演算法筆記
- 資料結構之MySQL獨愛B+樹(二叉樹、AVL樹、紅黑樹、B樹對比)資料結構MySql二叉樹
- 雜湊,二叉樹,紅黑樹,B樹,B+樹,LSM樹等資料結構做索引比較二叉樹資料結構索引
- Linux核心資料管理利器--紅黑樹Linux
- 重學資料結構和演算法(二)之二叉樹、紅黑樹、遞迴樹、堆排序資料結構演算法二叉樹遞迴排序
- 資料結構與演算法(十四)深入理解紅黑樹和JDK TreeMap和TreeSet原始碼分析資料結構演算法JDK原始碼
- 紅黑樹
- 演算法導論學習--紅黑樹詳解之刪除(含完整紅黑樹程式碼)演算法
- jdk1.8原始碼解析:HashMap底層資料結構之連結串列轉紅黑樹的具體時機JDK原始碼HashMap資料結構
- 資料結構 - 樹,三探之程式碼實現資料結構
- 資料結構中樹形結構簡介資料結構
- 資料結構之樹結構概述(含滿二叉樹、完全二叉樹、平衡二叉樹、二叉搜尋樹、紅黑樹、B-樹、B+樹、B*樹)資料結構二叉樹
- 資料結構——樹資料結構
- 資料結構-樹資料結構
- 瞭解紅黑樹的起源,理解紅黑樹的本質
- JavaScript中的樹型資料結構JavaScript資料結構
- 紅黑樹左右旋
- 淺談紅黑樹
- 紅黑樹詳解
- 資料結構專題頁(更新中...)資料結構
- 從紅黑樹的本質出發,徹底理解紅黑樹!
- 【從蛋殼到滿天飛】JS 資料結構解析和演算法實現-紅黑樹(一)JS資料結構演算法
- 紅黑樹這個資料結構,讓你又愛又恨?看了這篇,妥妥的征服它資料結構
- 0731 – 搞定 iPaste for iOS 資料結構ASTiOS資料結構
- 『資料結構』樹(Tree)資料結構
- 資料結構-字典樹資料結構
- 資料結構之「樹」資料結構
- 資料結構 - 樹,初探資料結構
- 資料結構 - AVL 樹資料結構