golang红黑树

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.总结

菜鸟写法,测试虽然有用,但是效率比之前写过的平衡二叉树要低,以后有机会进行优化,欢迎各位大佬指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值