Golang program to search for a node in a Red Black Tree


Searching a node in a red black tree is to find a node with a specific key or value. The search in the red black tree is similar to searching in a standard binary tree. In this article, we will write Go language programs to search for a node in a Red Black tree. It is a self-balancing Binary search tree with coloring properties where the root node is always black and other nodes are red or black as per the properties. This tree uses rotations to maintain the balance during insertions and deletions.

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

Syntax

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

To create a red black tree.

func (t *RedBlackTree) Insert(data int) { // ... }

To insert a new node containing data to the tree.

func (t *RedBlackTree) leftRotate(node *Node) { // ... }

To perform a left rotation on the tree.

func (t *RedBlackTree) Search(key int) *Node { // ... }

To search a node with a specific key value.

Algorithm

  • Import the required packages

  • Create a constant of type "Colour" with the values "Red" and "Black" assigned as 0 and 1, respectively.

  • Define data structures Make a struct called "RedBlackTree" with a single field called "root" that points to the root node.

  • Create a function named "NewRedBlackTree" that creates and returns a new instance of the Red-Black Tree structure.

Example 1

In the below example a red black tree is defined using a struct, consisting of a root node. The below code contains construction, insertion and search operation in a red black tree, highlighting the self balancing feature and capability of fast searches of the data structure.

package main

import "fmt"

type Color int

const (
   Red   Color = 0
   Black Color = 1
)

type Node struct {
   data        int
   color       Color
   left, right *Node
   parent      *Node
}

type RedBlackTree struct {
   root *Node
}

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

func (t *RedBlackTree) Insert(data int) {
   newNode := &Node{data: data, color: Red}
   t.insertNode(newNode)

   t.fixInsertion(newNode)
}

func (t *RedBlackTree) insertNode(newNode *Node) {
   if t.root == nil {
      t.root = newNode
      return
   }

   current := t.root
   var parent *Node
   for current != nil {
      parent = current
      if newNode.data < current.data {
         current = current.left
      } else if newNode.data > current.data {
         current = current.right
      } else {
         
         return
      }
   }

   newNode.parent = parent
   if newNode.data < parent.data {
      parent.left = newNode
   } else {
      parent.right = newNode
   }
}

func (t *RedBlackTree) fixInsertion(node *Node) {
   for node.parent != nil && 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.rightRotate(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.rightRotate(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) rightRotate(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) Search(key int) *Node {
   current := t.root
   for current != nil {
      if key == current.data {
         return current
      } else if key < current.data {
         current = current.left
      } else {
         current = current.right
      }
   }
   return nil
}

func main() {
   tree := NewRedBlackTree()

   tree.Insert(60)
   tree.Insert(40)
   tree.Insert(20)
   tree.Insert(40)
   tree.Insert(30)

   search_key := 40
   result := tree.Search(search_key)
   if result != nil {
      fmt.Printf("Node with value %d found\n", search_key)
   } else {
      fmt.Printf("Node with value %d not found\n", search_key)
   }
}

Output

Node with value 40 found.

Conclusion

In this article we have discussed how we can search for a node in a red black tree. To search a value we first created a red black tree, inserted a node with data to it and then searched for a particular value. Red black tree are used to represent directory and files in file managing systems, it can be used as a priority queue in a scheduler, it can be modified to implement interval tree and many more, these are few applications where red black tree can be used in go language.

Updated on: 05-Jul-2023

70 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements