This article provides an implementation of a Red-Black Tree in Go, covering its structure, properties, and example usage.
Red-Black Tree, Go Programming, Data Structures, Tree Algorithms
package main
import "fmt"
type Color bool
const (
RED Color = true
BLACK Color = false
)
type Node struct {
Key int
Color Color
Left *Node
Right *Node
Parent *Node
}
type RedBlackTree struct {
Root *Node
Nil *Node
}
func NewRedBlackTree() *RedBlackTree {
nilNode := &Node{Color: BLACK}
return &RedBlackTree{Nil: nilNode, Root: nilNode}
}
func (t *RedBlackTree) Insert(key int) {
newNode := &Node{Key: key, Color: RED, Left: t.Nil, Right: t.Nil}
t.insertBST(newNode)
t.fixInsert(newNode)
}
func (t *RedBlackTree) insertBST(z *Node) {
y := t.Nil
x := t.Root
for x != t.Nil {
y = x
if z.Key < x.Key {
x = x.Left
} else {
x = x.Right
}
}
z.Parent = y
if y == t.Nil {
t.Root = z
} else if z.Key < y.Key {
y.Left = z
} else {
y.Right = z
}
}
func (t *RedBlackTree) fixInsert(z *Node) {
for z.Parent.Color == RED {
if z.Parent == z.Parent.Parent.Left {
y := z.Parent.Parent.Right
if y.Color == RED {
z.Parent.Color = BLACK
y.Color = BLACK
z.Parent.Parent.Color = RED
z = z.Parent.Parent
} else {
if z == z.Parent.Right {
z = z.Parent
t.LeftRotate(z)
}
z.Parent.Color = BLACK
z.Parent.Parent.Color = RED
t.RightRotate(z.Parent.Parent)
}
} else {
y := z.Parent.Parent.Left
if y.Color == RED {
z.Parent.Color = BLACK
y.Color = BLACK
z.Parent.Parent.Color = RED
z = z.Parent.Parent
} else {
if z == z.Parent.Left {
z = z.Parent
t.RightRotate(z)
}
z.Parent.Color = BLACK
z.Parent.Parent.Color = RED
t.LeftRotate(z.Parent.Parent)
}
}
}
t.Root.Color = BLACK
}
func (t *RedBlackTree) LeftRotate(x *Node) {
// Implementation of left rotation
}
func (t *RedBlackTree) RightRotate(y *Node) {
// Implementation of right rotation
}
func main() {
rbTree := NewRedBlackTree()
rbTree.Insert(10)
rbTree.Insert(20)
rbTree.Insert(30)
fmt.Println("Red-Black Tree created with inserted nodes.")
}
How do I avoid rehashing overhead with std::set in multithreaded code?
How do I find elements with custom comparators with std::set for embedded targets?
How do I erase elements while iterating with std::set for embedded targets?
How do I provide stable iteration order with std::unordered_map for large datasets?
How do I reserve capacity ahead of time with std::unordered_map for large datasets?
How do I erase elements while iterating with std::unordered_map in multithreaded code?
How do I provide stable iteration order with std::map for embedded targets?
How do I provide stable iteration order with std::map in multithreaded code?
How do I avoid rehashing overhead with std::map in performance-sensitive code?
How do I merge two containers efficiently with std::map for embedded targets?