Created
July 27, 2023 14:37
-
-
Save flyhigher139/9322716a9fdfcbce7c8123c11cc083aa to your computer and use it in GitHub Desktop.
red_black_tree.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Node[K any, V any] struct { | |
Key K | |
Value V | |
Red bool | |
Left *Node[K, V] | |
Right *Node[K, V] | |
Parent *Node[K, V] | |
} | |
type RedBlackTree[K any, V any] struct { | |
Root *Node[K, V] | |
compare comparable.Comparator[K] | |
} | |
func NewNode[K any, V any](key K, value V) *Node[K, V] { | |
return &Node[K, V]{Key: key, Value: value, Red: true} | |
} | |
func NewRedBlackTree[K any, V any](compare comparable.Comparator[K]) *RedBlackTree[K, V] { | |
return &RedBlackTree[K, V]{ | |
compare: compare, | |
} | |
} | |
func (t *RedBlackTree[K, V]) Insert(key K, value V) error { | |
newNode := NewNode(key, value) | |
if t.Root == nil { | |
t.Root = newNode | |
} else { | |
t.insertRec(t.Root, newNode) | |
} | |
t.Root.Red = false | |
return nil | |
} | |
func (t *RedBlackTree[K, V]) insertRec(root, newNode *Node[K, V]) { | |
if root == nil { | |
return | |
} | |
if t.compare(newNode.Key, root.Key) < 0 { | |
if root.Left == nil { | |
root.Left = newNode | |
newNode.Parent = root | |
} else { | |
t.insertRec(root.Left, newNode) | |
} | |
} else if t.compare(root.Key, newNode.Key) < 0 { | |
if root.Right == nil { | |
root.Right = newNode | |
newNode.Parent = root | |
} else { | |
t.insertRec(root.Right, newNode) | |
} | |
} | |
t.fixViolation(newNode) | |
} | |
func (t *RedBlackTree[K, V]) fixViolation(node *Node[K, V]) { | |
parentNode := node.Parent | |
if parentNode == nil { | |
node.Red = false | |
} else if parentNode.Red { | |
grandParentNode := parentNode.Parent | |
if grandParentNode == nil { | |
return | |
} | |
if node == parentNode.Right && parentNode == grandParentNode.Left { | |
t.rotateLeft(parentNode) | |
node = parentNode | |
parentNode = node.Parent | |
} else if node == parentNode.Left && parentNode == grandParentNode.Right { | |
t.rotateRight(parentNode) | |
node = parentNode | |
parentNode = node.Parent | |
} | |
if parentNode == grandParentNode.Left { | |
t.rotateRight(grandParentNode) | |
} else { | |
t.rotateLeft(grandParentNode) | |
} | |
parentNode.Red = false | |
grandParentNode.Red = true | |
if grandParentNode == t.Root { | |
grandParentNode.Red = false | |
} | |
} | |
} | |
func (t *RedBlackTree[K, V]) rotateLeft(node *Node[K, V]) { | |
rightNode := node.Right | |
node.Right = rightNode.Left | |
if node.Right != nil { | |
node.Right.Parent = node | |
} | |
rightNode.Parent = node.Parent | |
if node.Parent == nil { | |
t.Root = rightNode | |
} else if node == node.Parent.Left { | |
node.Parent.Left = rightNode | |
} else { | |
node.Parent.Right = rightNode | |
} | |
rightNode.Left = node | |
node.Parent = rightNode | |
} | |
func (t *RedBlackTree[K, V]) rotateRight(node *Node[K, V]) { | |
leftNode := node.Left | |
node.Left = leftNode.Right | |
if node.Left != nil { | |
node.Left.Parent = node | |
} | |
leftNode.Parent = node.Parent | |
if node.Parent == nil { | |
t.Root = leftNode | |
} else if node == node.Parent.Right { | |
node.Parent.Right = leftNode | |
} else { | |
node.Parent.Left = leftNode | |
} | |
leftNode.Right = node | |
node.Parent = leftNode | |
} | |
func (t *RedBlackTree[K, V]) Delete(key K) error { | |
node := t.searchRec(t.Root, key) | |
if node != nil { | |
t.deleteNode(node) | |
} | |
return nil | |
} | |
func (t *RedBlackTree[K, V]) searchRec(root *Node[K, V], key K) *Node[K, V] { | |
if root == nil || t.compare(root.Key, key) == 0 { | |
return root | |
} | |
if t.compare(key, root.Key) < 0 { | |
return t.searchRec(root.Left, key) | |
} else { | |
return t.searchRec(root.Right, key) | |
} | |
} | |
func (t *RedBlackTree[K, V]) deleteNode(node *Node[K, V]) { | |
y := node | |
color := y.Red | |
var x, xParent *Node[K, V] | |
if node.Left == nil { | |
x = node.Right | |
t.transplant(node, node.Right) | |
} else if node.Right == nil { | |
x = node.Left | |
t.transplant(node, node.Left) | |
} else { | |
y = t.minimum(node.Right) | |
color = y.Red | |
x = y.Right | |
if y.Parent == node { | |
xParent = y | |
} else { | |
t.transplant(y, y.Right) | |
y.Right = node.Right | |
y.Right.Parent = y | |
} | |
t.transplant(node, y) | |
y.Left = node.Left | |
y.Left.Parent = y | |
y.Red = node.Red | |
} | |
if !color { | |
t.fixDeleteViolation(x, xParent) | |
} | |
} | |
func (t *RedBlackTree[K, V]) minimum(node *Node[K, V]) *Node[K, V] { | |
for node.Left != nil { | |
node = node.Left | |
} | |
return node | |
} | |
func (t *RedBlackTree[K, V]) transplant(u, v *Node[K, V]) { | |
if u.Parent == nil { | |
t.Root = v | |
} else if u == u.Parent.Left { | |
u.Parent.Left = v | |
} else { | |
u.Parent.Right = v | |
} | |
if v != nil { | |
v.Parent = u.Parent | |
} | |
} | |
func (t *RedBlackTree[K, V]) fixDeleteViolation(node, parentNode *Node[K, V]) { | |
for node != t.Root && (node == nil || !node.Red) { | |
if parentNode.Left == node { | |
siblingNode := parentNode.Right | |
if siblingNode.Red { | |
siblingNode.Red = false | |
parentNode.Red = true | |
t.rotateLeft(parentNode) | |
siblingNode = parentNode.Right | |
} | |
if (siblingNode.Left == nil || !siblingNode.Left.Red) && (siblingNode.Right == nil || !siblingNode.Right.Red) { | |
siblingNode.Red = true | |
node = parentNode | |
parentNode = node.Parent | |
} else { | |
if siblingNode.Right == nil || !siblingNode.Right.Red { | |
siblingNode.Left.Red = false | |
siblingNode.Red = true | |
t.rotateRight(siblingNode) | |
siblingNode = parentNode.Right | |
} | |
siblingNode.Red = parentNode.Red | |
parentNode.Red = false | |
if siblingNode.Right != nil { | |
siblingNode.Right.Red = false | |
} | |
t.rotateLeft(parentNode) | |
node = t.Root | |
} | |
} else { | |
siblingNode := parentNode.Left | |
if siblingNode.Red { | |
siblingNode.Red = false | |
parentNode.Red = true | |
t.rotateRight(parentNode) | |
siblingNode = parentNode.Left | |
} | |
if (siblingNode.Right == nil || !siblingNode.Right.Red) && (siblingNode.Left == nil || !siblingNode.Left.Red) { | |
siblingNode.Red = true | |
node = parentNode | |
parentNode = node.Parent | |
} else { | |
if siblingNode.Left == nil || !siblingNode.Left.Red { | |
siblingNode.Right.Red = false | |
siblingNode.Red = true | |
t.rotateLeft(siblingNode) | |
siblingNode = parentNode.Left | |
} | |
siblingNode.Red = parentNode.Red | |
parentNode.Red = false | |
if siblingNode.Left != nil { | |
siblingNode.Left.Red = false | |
} | |
t.rotateRight(parentNode) | |
node = t.Root | |
} | |
} | |
} | |
if node != nil { | |
node.Red = false | |
} | |
} | |
func (t *RedBlackTree[K, V]) Search(key K) (V, bool) { | |
node := t.searchRec(t.Root, key) | |
if node != nil { | |
return node.Value, true | |
} | |
var v V | |
return v, false | |
} | |
func (t *RedBlackTree[K, V]) Update(key K, value V) { | |
node := t.searchRec(t.Root, key) | |
if node != nil { | |
node.Value = value | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment