数据结构读书笔记(二)——红黑树

来源:互联网 发布:sql基础教程 编辑:程序博客网 时间:2024/06/05 22:46

2.1 红黑树的性质

2.1.1 背景知识

树的高度决定了树上操作的成本,一些搜索树高度如下:

平衡二叉搜索树:O(logn)

AVL树:<= 1.44logn

红黑树:<=2log(n + 1)

2.1.2 红黑树的定义

红黑树是满足下述性质的二叉搜索树:

1.每个节点必须为红色或者黑色

2.根为黑色

3.树中nil叶子为黑

4.若节点为红,则其两个孩子必为黑

5.每节点到其后代节点的所有路径含有同样多的黑节点

节点的结构:


2.1.3 黑高

节点x的黑高bh(x)是该节点到它任何后代叶子路径上的黑节点数(不包括x本身)。

红黑树的黑高是根的黑高。

2.1.4 高度的一个引理

一棵n个内点的红黑树高度至多是2log(n+1)。


2.2 旋转

2.2.1 左、右旋转定义

图示:


2.2.2 左旋实现步骤

图示:


1. y <- right[x] //记录直线y节点的指针

2. right[x] <- left[y], p[left[y]] <- x

3. p[y] <- p[x] //y连接到p[x]

4. left[y] <- x, p[x] <- y//x连接到y左

ps: 要注意先后顺序;每条边的修改涉及双向;要考虑临界情形。

2.2.3 左旋算法

LeftRotate(T,x){//假定right[x] != nil[T]//step 1y <- right[x];//step 2right[x] <- left[y];p[left[y]] <- x;//step 3p[y] <- p[x];if p[x] = nil[T] thenroot[T] <- y;else if x = left[p[x]]left[p[x]] <- y;elseright[p[x]] <- y;//step 4left[y] <- x;p[x] <- y;}

T(n) = O(1)


2.3 插入

2.3.1 算法步骤

1.将z节点按BST树规则插入红黑树中,z是叶子节点

2.将z涂红

3.调整使其满足红黑树的性质

2.3.2 RBInsert算法

RBInsert(T,x){y <- nil[T];//y用于记录:当前扫描节点的双亲节点x <- root[T];//从根开始扫描while x != nil[T] do//查找插入位置{y <- x;if key[z] < key[x]//z插入x的左边x <- left[x];elsex <- right[x];//z插入x的右边}p[z] <- y;//y是z的双亲if y = nil[T]//z插入空树root[T] <- z;//z是根else if key[z] = key[y]left[y] <- z;//z是y的左子插入elseright[y] <- z;//z是y的右子插入left[z] <- right[z] <- nil[T];color[z] <- red;RBInsertFixup(T,z);}

2.3.3 RBInsertFixup算法

思路:通过选择和改变颜色,自下而上调整(z进行上溯),使树满足红黑树。

z插入后违反情况,其两个孩子为黑,可能违反性质2:z是根;可能违反性质4:p[z]是红。

调整步骤:

(1)若z为根,将其涂黑

(2)若z为非根,则p[z]存在

1.若p[z]为黑,无需调整

2.若p[z]为红,违反性质4,则需调整

分6种情况进行调整:

case1-3为z的双亲p[z]是其祖父p[p[z]]的左孩子

case1-3为z的双亲p[z]是其祖父p[p[z]]的右孩子


2.4 删除

2.4.1 分析讨论

z删除后BST的调整

case 1:z为叶子

case 2:z只有一个孩子

case 3:z有两个孩子

BST性质的影响:删红点不影响,删黑点需要调整

2.4.2 删除算法

RBDelete(T,x){if(left[z] = nil) or (right[z] = nil)y <- z;//后面进行物理删除yelse//z的两子树均非空,case 3y <- TreeSuccessor(z);//y是z的中序后继//此时,y统一地是x的双亲节点且是要删除节点//x是待连接到p[y]的节点,以下要确定xif left[y] != nil//综合case1,2,3x <- left[y];elsex <- right[y];//用x取代y与y的双亲连接if p[y] = nil//y是根 root[T] <- x;else//y非根if (y = left[p[y]]) {//y是双亲的左子left[p[y]] <- x;}elseright[p[y]] <- x;if y != z  //case 3y copy to z;if color[y] = blackRBDeleteFixup(T,x);return y;//实际是删除y节点}

调整算法:RBDeleteFixup(T,x)

x:或是y的唯一孩子;或是哨兵nil

想象将y的黑色涂到x上,

若x为红,只要将其涂黑,调整即可终止;

若x为黑,将y的黑色涂上之后,x是一个双黑节点,违反性质1。

处理步骤如下:

1.若x是根,直接移去多余一层黑色(树黑高减1),终止。

2.若x原为红,将y的黑色涂到x上,终止。

3.若x非根节点,且为黑色,则x为双黑。通过变色、旋转使多余黑色向上传播,直到某个红色节点或传到根。

调整分8种情况:case1-4是x为p[x]的左子,case1-4是x为p[x]的右子