go语言红黑树
1.红黑树基础
1.结点不是红色就是黑色
2.根结点为黑色结点
3.所有叶子结点为黑色结点(叶子结点为nil结点)
4.红色结点的子结点必为黑色结点(叶子结点到根结点的路径上没有两个连续的红色结点)
5.从任一结点到叶子结点的路径上必有相同数目的黑色结点
2.泛型类型定义
type AVLType interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~float32 | ~float64 | ~string | ~uintptr
}
//红黑结点
const (
RED = 0
BLACK = 1
)
3.红黑树结构定义
//红黑树
type RedBlackTree[T AVLType] struct {
lock *sync.RWMutex //互斥锁
node *redBlackNode[T] //红黑树根结点
colorChange bool //变色标志
}
//红黑树结点
type redBlackNode[T AVLType] struct {
data T
lChild, rChild *redBlackNode[T]
color int
parent *redBlackNode[T]
}
4.红黑树结点的左旋与右旋
//结点左旋
func (r *redBlackNode[T]) leftRotate() *redBlackNode[T] {
if r != nil {
var R *redBlackNode[T]
R = r.rChild
r.rChild = R.lChild
//左子树不为空需要更新父节点
if R.lChild != nil {
R.lChild.parent = r
}
if r.parent != nil && r == r.parent.lChild {
r.parent.lChild = R
} else if r.parent != nil && r == r.parent.rChild {
r.parent.rChild = R
}
//空出r的父节点
R.parent = r.parent
R.lChild = r
r.parent = R
r = R
}
return r
}
//结点右旋
func (r *redBlackNode[T]) rightRotate() *redBlackNode[T] {
if r != nil {
var L *redBlackNode[T]
L = r.lChild
r.lChild = L.rChild
//右子树不为空则更新父节点
if L.rChild != nil {
L.rChild.parent = r
}
if r.parent != nil && r == r.parent.lChild {
r.parent.lChild = L
} else if r.parent != nil && r == r.parent.rChild {
r.parent.rChild = L
}
L.parent = r.parent
L.rChild = r
r.parent = L
r = L
}
return r
}
5.红黑树的插入
//红黑树插入
func (r *RedBlackTree[T]) InsertRBT(e T) {
r.lock.Lock()
defer r.lock.Unlock()
r.colorChange = false
newNode := r.node.insertNode(e, &r.colorChange)
if newNode.color == RED {
newNode.parent = nil
newNode.color = BLACK
}
r.node = newNode
}
//红黑树结点的插入
func (r *redBlackNode[T]) insertNode(e T, color *bool) *redBlackNode[T] {
if r == nil {
r = &redBlackNode[T]{
data: e,
lChild: nil,
rChild: nil,
color: RED,
parent: nil,
}
*color = true //要进行变色
return r
} else {
if r.data == e {
//已有该值,直接返回
*color = false
return r
} else if e < r.data {
//插入左子树
newNode := r.lChild.insertNode(e, color)
if *color {
if r.color == BLACK {
//父节点黑色 无需操作
if r == newNode {
r.color = RED
*color = true
return r
}
newNode.parent = r //将新插入的节点接上
r.lChild = newNode
*color = false
return r
} else if (r.color == RED && r == r.parent.rChild && r.parent.lChild != nil && r.parent.lChild.color == RED) || (r.color == RED && r == r.parent.lChild && r.parent.rChild != nil && r.parent.rChild.color == RED) {
//父节点和叔结点都是红色 父叔都变黑,祖父变红 然后递归
r.lChild = newNode //将当前节点与新节点连接
newNode.parent = r
r.parent.lChild.color = BLACK
r.parent.rChild.color = BLACK
//r.parent.color = RED
//newNode.parent = r
*color = true
return r.parent //返回祖父结点继续调整
} else if r.color == RED && r == r.parent.lChild {
//左左 右旋加变色
r.lChild = newNode //将当前节点与新节点连接
newNode.parent = r
tmp := r.parent.rightRotate()
tmp.color = BLACK
tmp.rChild.color = RED
*color = false
return tmp
} else {
//右左 先右旋在左旋 变色
r.lChild = newNode //将当前节点与新节点连接
newNode.parent = r
tmp1 := r.rightRotate()
tmp2 := tmp1.parent.leftRotate()
tmp2.color = BLACK
tmp2.lChild.color = RED
*color = false
return tmp2
}
}
if newNode.parent == nil {
return newNode //旋转完成后如果变成了根结点则返回根结点
}
} else {
//插入右子树
newNode := r.rChild.insertNode(e, color)
if *color {
if r.color == BLACK {
//父节点黑色 无需操作
if r == newNode {
r.color = RED
*color = true
return r
}
newNode.parent = r //将新插入的节点接上
r.rChild = newNode
*color = false
return r
} else if (r.color == RED && r == r.parent.rChild && r.parent.lChild != nil && r.parent.lChild.color == RED) || (r.color == RED && r == r.parent.lChild && r.parent.rChild != nil && r.parent.rChild.color == RED) {
//父节点和叔结点都是红色 父叔都变黑,祖父变红 然后递归
r.rChild = newNode //将当前节点与新节点连接
newNode.parent = r
r.parent.lChild.color = BLACK
r.parent.rChild.color = BLACK
//r.parent.color = RED
//newNode.parent = r
*color = true
return r.parent //返回祖父结点继续调整
} else if r.color == RED && r == r.parent.rChild {
//右右 左旋加变色
r.rChild = newNode //将当前节点与新节点连接
newNode.parent = r
tmp := r.parent.leftRotate()
tmp.color = BLACK
tmp.lChild.color = RED
*color = false
return tmp
} else {
//左右 先左旋在右旋 变色
r.rChild = newNode //将当前节点与新节点连接
newNode.parent = r
tmp1 := r.leftRotate()
tmp2 := tmp1.parent.rightRotate()
tmp2.color = BLACK
tmp2.rChild.color = RED
*color = false
return tmp2
}
}
if newNode.parent == nil {
//r.rChild = newNode
return newNode //旋转完成后如果变成了根结点则返回根结点
}
}
}
return r
}
6.红黑树的删除
//红黑树结点删除
func (r *redBlackNode[T]) deleteRBTNode(e T, color *bool) *redBlackNode[T] {
if r == nil {
*color = false
return r
} else {
if e == r.data {
//找到待删除结点,开始做删除操作
if r.color == RED && r.lChild == nil && r.rChild == nil {
//删除红叶子节点,直接删除
*color = false
if r == r.parent.lChild {
r.parent.lChild = nil
} else {
r.parent.rChild = nil
}
return nil
} else if r.color == BLACK && r.lChild == nil && r.rChild == nil {
//删除黑色叶子结点,分四种情况讨论
if (r == r.parent.lChild && r.parent.rChild != nil && r.parent.rChild.color == RED) || (r == r.parent.rChild && r.parent.lChild != nil && r.parent.lChild.color == RED) {
//兄弟结点为红色,转为兄弟结点为黑色
if r == r.parent.lChild {
//如果是左孩子 则左旋加变色
tmp := r.parent.leftRotate()
tmp.color = BLACK
tmp.lChild.color = RED
} else {
//如果是右孩子 则右旋加变色
tmp := r.parent.rightRotate()
tmp.color = BLACK
tmp.lChild.color = RED
}
}
if r.parent.color == RED && ((r == r.parent.lChild && r.parent.rChild != nil && r.parent.rChild.lChild == nil && r.parent.rChild.rChild == nil) || (r == r.parent.rChild && r.parent.lChild != nil && r.parent.lChild.lChild == nil && r.parent.lChild.rChild == nil)) {
//父节点为红色且侄子结点(兄弟结点的子节点)均为nil
if r == r.parent.lChild { //删除结点
r.parent.lChild = nil
r.parent.rChild.color = RED //兄弟涂红
} else {
r.parent.rChild = nil
r.parent.lChild.color = RED
}
*color = false
r.parent.color = BLACK //父结点涂黑
return r.parent
} else if r.parent.color == BLACK && ((r == r.parent.lChild && r.parent.rChild != nil && r.parent.rChild.lChild == nil && r.parent.rChild.rChild == nil) || (r == r.parent.rChild && r.parent.lChild != nil && r.parent.lChild.lChild == nil && r.parent.lChild.rChild == nil)) {
//父结点为黑色且侄子结点为nil
if r == r.parent.lChild { //删除结点
r.parent.lChild = nil
r.parent.rChild.color = RED //兄弟涂红
} else {
r.parent.rChild = nil
r.parent.lChild.color = RED
}
*color = true
return r.parent
} else {
if r == r.parent.lChild {
if r.parent.rChild.lChild != nil && r.parent.rChild.lChild.color == RED {
//左侄子为红色
r.parent.lChild = nil //删除结点
tmp1 := r.parent.rChild.rightRotate()
tmp1.color = r.parent.color
r.parent.color = BLACK
tmp2 := r.parent.leftRotate()
*color = false
return tmp2
} else if r.parent.rChild.rChild != nil && r.parent.rChild.rChild.color == RED {
//右侄子为红色
r.parent.lChild = nil
r.parent.rChild.color = r.parent.color
r.parent.color = BLACK
r.parent.rChild.rChild.color = BLACK
tmp := r.parent.leftRotate() //左旋
return tmp
}
} else if r == r.parent.rChild {
if r.parent.lChild.rChild != nil && r.parent.lChild.rChild.color == RED {
//右侄子为红色
r.parent.rChild = nil //删除结点
tmp1 := r.parent.lChild.leftRotate()
tmp1.color = r.parent.color
r.parent.color = BLACK
tmp2 := r.parent.rightRotate()
*color = false
return tmp2
} else if r.parent.lChild.lChild != nil && r.parent.lChild.lChild.color == RED {
//左侄子为红色
r.parent.rChild = nil
r.parent.lChild.color = r.parent.color
r.parent.color = BLACK
r.parent.lChild.lChild.color = BLACK
tmp := r.parent.rightRotate() //右旋
return tmp
}
}
}
} else if r.lChild != nil && r.rChild == nil {
//删除结点只有左孩子,将左孩子的值赋值给当前结点,并删除左孩子
r.data = r.lChild.data
r.lChild = nil
*color = false
return r
} else if r.rChild != nil && r.lChild == nil {
//删除结点只有右孩子,将右孩子的值赋值给当前结点,并删除右孩子
r.data = r.rChild.data
r.rChild = nil
*color = false
return r
} else {
//左右结点都存在,找到前驱结点,并将值替换,删除前驱结点
L := r.lChild
for L.rChild != nil {
L = L.rChild
}
r.data = L.data
L.deleteRBTNode(L.data, color)
return r
}
} else if e < r.data {
//去左子树找待删除结点
newNode := r.lChild.deleteRBTNode(e, color)
if *color {
for !*color {
if newNode.parent == nil {
break
}
newNode, *color = deleteFixUp(newNode)
}
}
if newNode != nil && newNode.parent == nil {
return newNode
}
} else {
//去右子树找待删除结点
newNode := r.rChild.deleteRBTNode(e, color)
if *color {
for !*color {
if newNode.parent == nil {
break
}
newNode, *color = deleteFixUp(newNode)
}
}
if newNode != nil && newNode.parent == nil {
return newNode
}
}
}
return r
}
//删除调整
func deleteFixUp[T AVLType](r *redBlackNode[T]) (*redBlackNode[T], bool) {
var color bool
if (r == r.parent.lChild && r.parent.rChild != nil && r.parent.rChild.color == RED) || (r == r.parent.rChild && r.parent.lChild != nil && r.parent.lChild.color == RED) {
//兄弟结点为红色,转为兄弟结点为黑色
if r == r.parent.lChild {
//如果是左孩子 则左旋加变色
tmp := r.parent.leftRotate()
tmp.color = BLACK
tmp.lChild.color = RED
} else {
//如果是右孩子 则右旋加变色
tmp := r.parent.rightRotate()
tmp.color = BLACK
tmp.lChild.color = RED
}
}
if r.parent.color == RED && ((r == r.parent.lChild && r.parent.rChild != nil && r.parent.rChild.lChild == nil && r.parent.rChild.rChild == nil) || (r == r.parent.rChild && r.parent.lChild != nil && r.parent.lChild.lChild == nil && r.parent.lChild.rChild == nil)) {
//父节点为红色且侄子结点(兄弟结点的子节点)均为nil
if r == r.parent.lChild {
//r.parent.lChild = nil
r.parent.rChild.color = RED //兄弟涂红
} else {
//r.parent.rChild = nil
r.parent.lChild.color = RED
}
color = false
r.parent.color = BLACK //父结点涂黑
return r.parent, color
} else if r.parent.color == BLACK && ((r == r.parent.lChild && r.parent.rChild != nil && r.parent.rChild.lChild == nil && r.parent.rChild.rChild == nil) || (r == r.parent.rChild && r.parent.lChild != nil && r.parent.lChild.lChild == nil && r.parent.lChild.rChild == nil)) {
//父结点为黑色且侄子结点为nil
if r == r.parent.lChild {
//r.parent.lChild = nil
r.parent.rChild.color = RED //兄弟涂红
} else {
//r.parent.rChild = nil
r.parent.lChild.color = RED
}
color = true
return r.parent, color
} else {
if r == r.parent.lChild {
if r.parent.rChild.lChild != nil && r.parent.rChild.lChild.color == RED {
//左侄子为红色
//r.parent.lChild = nil //删除结点
tmp1 := r.parent.rChild.rightRotate()
tmp1.color = r.parent.color
r.parent.color = BLACK
tmp2 := r.parent.leftRotate()
color = false
return tmp2, color
} else if r.parent.rChild.rChild != nil && r.parent.rChild.rChild.color == RED {
//右侄子为红色
//r.parent.lChild = nil
r.parent.rChild.color = r.parent.color
r.parent.color = BLACK
r.parent.rChild.rChild.color = BLACK
tmp := r.parent.leftRotate() //左旋
return tmp, color
}
} else if r == r.parent.rChild {
if r.parent.lChild.rChild != nil && r.parent.lChild.rChild.color == RED {
//右侄子为红色
//r.parent.rChild = nil //删除结点
tmp1 := r.parent.lChild.leftRotate()
tmp1.color = r.parent.color
r.parent.color = BLACK
tmp2 := r.parent.rightRotate()
color = false
return tmp2, color
} else if r.parent.lChild.lChild != nil && r.parent.lChild.lChild.color == RED {
//左侄子为红色
//r.parent.rChild = nil
r.parent.lChild.color = r.parent.color
r.parent.color = BLACK
r.parent.lChild.lChild.color = BLACK
tmp := r.parent.rightRotate() //右旋
return tmp, color
}
}
}
return r, color
}
7.总结
菜鸟写法,测试虽然有用,但是效率比之前写过的平衡二叉树要低,以后有机会进行优化,欢迎各位大佬指正!