红黑树 插入调整步骤终极详解

     看了很多资料,网上讲红黑树插入删除讲得实在太乱了,没有统一的步骤,让初学者容易混乱。这里我整理下,左旋右旋就不详解了。直接看插入删除的具体操作。

   我就不画图了,借助https://www.cs.usfca.edu/~galles/visualization/RedBlack.html来直接截图给大家演示

1.插入

      插入的节点默认是红节点

      1.1 找到插入的位置,将该节点插入,若该节点的父节点为黑,红黑树性质继续保持,操作完成。

      1.2 若父节点为红色,则红黑树性质被破坏,需要进行调整。

      case 1:当叔父节点为红时(插入节点为6,叔父节点为9)

    =》 =》

     处理方法:将父结点和叔父结点变为黑色,祖父结点变为红色。将祖父结点作为新插入的结点继续向上迭代进行平衡操作,在迭代时如果调整到根,则根为黑色,跳出循环(否则继续循环,循环结束条件为当前节点的父节点颜色为黑色),调整完毕。

  case 2:叔父节点为黑,插入节点,父亲节点,祖父节点三者不在一条直线上(插入节点为24,叔父节点为黑色(空叶子节点为黑色))

=》  

   处理方法:以父亲节点右旋(若插入节点是父亲节点的右儿子则左旋),将父亲节点看为新的插入节点(即图中的插入节点变为22),将情况转化为case3,交给case 3处理。

     case 3:叔父节点为黑,插入节点,父亲节点,祖父节点三者在一条直线上(插入节点黑21,叔父节点为黑色(空叶子节点为黑色))

    =》

   处理方法:交换父亲节点和祖父节点的颜色,然和以祖父节点右旋(如若这根直线是斜向下的则进行左旋操作),则调整结束。

插入调整总结起来就这三种情况,下面给出插入调整的golang代码。

func (rbt *RBTree) insertBalanceFixup(insertnode *TreeNode) {
	var uncle *TreeNode
	for insertnode.parent.color == "red" {
		grandfather := insertnode.parent.parent //父节点为红,肯定不为根节点,则存在祖父节点
		if insertnode.parent == grandfather.lchild {
			uncle = grandfather.rchild
		} else {
			uncle = grandfather.lchild
		}
		if uncle.color == "red" { //case 1
			uncle.color, insertnode.parent.color = "black", "black"
			insertnode = grandfather
			if insertnode == rbt.root {
				return
			}
			grandfather.color = "red"
			continue
		}
		//叔叔为黑
		parent := insertnode.parent
		if parent == grandfather.lchild { //父亲为左儿子
			if insertnode == parent.rchild { //case2
				insertnode = parent
				rbt.LeftRotate(insertnode)
			}
			insertnode = insertnode.parent //case3
			insertnode.color = "black"
			insertnode = insertnode.parent
			insertnode.color = "red"
			rbt.RightRotate(insertnode)
		} else { //父亲为右儿子
			if insertnode == parent.lchild { //case2
				insertnode = parent
				rbt.RightRotate(insertnode)
			}
			insertnode = insertnode.parent //case3
			insertnode.color = "black"
			insertnode = insertnode.parent
			insertnode.color = "red"
			rbt.LeftRotate(insertnode)
		}
		return
	}
}

猜你喜欢

转载自blog.csdn.net/anliayx/article/details/86476838