Golang program to insert a new node into a Red Black Tree


In this article, we will write a Go language program to insert a node into a Red Black tree. A Red Black tree. It is a self-balancing Binary search tree having the following properties −

  • Every node is either red or black

  • The root node is always black

  • All leaves are taken as black

  • If a node is red, both its children will be black

  • Every path from a node to its descendant leaves contains the same number of black nodes

Algorithm

  • Create a "Node" struct with four fields: "key" of type int, "colour" of type string, "left" child, "right" child, and "parent" of type Node.

  • Make a RedBlackTree struct with a "root" field that points to the tree's root node.

  • To insert values into the Red-Black Tree, use the Insert technique. Create a new node with the specified key and the colour "red" set.

  • After inserting the new node, use the fixViolation technique to resolve any potential issues in the Red-Black Tree.

  • Use helper methods such as leftRotate and rightRotate to make left and right rotations on tree nodes.

  • Make a primary function. Make a new Red-Black Tree object. Using the Insert technique, add nodes to the tree.

  • Perform an inorder traversal and report the results with the fmt package's Println function.

Example

In this example, we will write a Go language program to insert a node into a Red Black tree using insert method and then printing inorder traversal to prove correctness of insertion algorithm.

package main

import "fmt"

type Node struct {
   key    int
   color  string
   left   *Node
   right  *Node
   parent *Node
}

type RedBlackTree struct {
   root *Node
}

func NewRedBlackTree() *RedBlackTree {
   return &RedBlackTree{}
}

func (t *RedBlackTree) Insert(key int) {
   node := &Node{
      key:   key,
      color: "red",
   }

   if t.root == nil {
      t.root = node
   } else {
      t.insertNode(t.root, node)
   }

   t.fixViolation(node)
}

func (t *RedBlackTree) insertNode(root, node *Node) {
   if node.key < root.key {
      if root.left == nil {
         root.left = node
         node.parent = root
      } else {
         t.insertNode(root.left, node)
      }
   } else {
      if root.right == nil {
         root.right = node
         node.parent = root
      } else {
         t.insertNode(root.right, node)
      }
   }
}

func (t *RedBlackTree) fixViolation(node *Node) {
   for node != t.root && node.parent.color == "red" {
      if node.parent == node.parent.parent.left {
         uncle := node.parent.parent.right

         if uncle != nil && uncle.color == "red" {
            node.parent.color = "black"
            uncle.color = "black"
            node.parent.parent.color = "red"
            node = node.parent.parent
         } else {
            if node == node.parent.right {
               node = node.parent
               t.leftRotate(node)
            }

            node.parent.color = "black"
            node.parent.parent.color = "red"
            t.right_rotate(node.parent.parent)
         }
      } else {
         uncle := node.parent.parent.left

         if uncle != nil && uncle.color == "red" {
            node.parent.color = "black"
            uncle.color = "black"
            node.parent.parent.color = "red"
            node = node.parent.parent
         } else {
            if node == node.parent.left {
               node = node.parent
               t.right_rotate(node)
            }

            node.parent.color = "black"
            node.parent.parent.color = "red"
            t.leftRotate(node.parent.parent)
         }
      }
   }

   t.root.color = "black"
}

func (t *RedBlackTree) leftRotate(node *Node) {
   rightChild := node.right
   node.right = rightChild.left

   if rightChild.left != nil {
      rightChild.left.parent = node
   }

   rightChild.parent = node.parent

   if node.parent == nil {
      t.root = rightChild
   } else if node == node.parent.left {
      node.parent.left = rightChild
   } else {
      node.parent.right = rightChild
   }

   rightChild.left = node
   node.parent = rightChild
}

func (t *RedBlackTree) right_rotate(node *Node) {
   leftChild := node.left
   node.left = leftChild.right

   if leftChild.right != nil {
      leftChild.right.parent = node
   }

   leftChild.parent = node.parent

   if node.parent == nil {
      t.root = leftChild
   } else if node == node.parent.left {
      node.parent.left = leftChild
   } else {
      node.parent.right = leftChild
   }

   leftChild.right = node
   node.parent = leftChild
}

func (t *RedBlackTree) Inorder_traversal(node *Node) {
   if node != nil {
      t.Inorder_traversal(node.left)
      fmt.Printf("%d ", node.key)
      t.Inorder_traversal(node.right)
   }
}

func main() {
   tree := NewRedBlackTree()

   tree.Insert(7)
   tree.Insert(3)
   tree.Insert(18)
   tree.Insert(10)
   tree.Insert(22)
   tree.Insert(8)
   tree.Insert(11)
   tree.Insert(26)
   tree.Insert(2)
   tree.Insert(6)
   tree.Insert(13)

   fmt.Println("Inorder traversal of the Red-Black Tree:")
   tree.Inorder_traversal(tree.root)
}

Output

Inorder traversal of the Red-Black Tree:
2 3 6 7 8 10 11 13 18 22 26

Conclusion

In this article we have discussed how we can insert a new node into a redblack tree in golanguage. Here in the example we have executed a program of inserting a new node into the Red-Black tree using the Insert method, and then printing the inorder traversal. This method is simple and straightforward and can be used anytime depending on the demand of the problem in hand.

Updated on: 05-Jul-2023

70 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements