Data Structures ADTs Implementation (In Go)

Data Structures ADTs Implementation (In Go)

Linked list

package main 

import "fmt"

func main (){

	var l = LinkedList{}
	var p Person= Person{"Abdulrahman",3} 

	l.insert(&p)
	l.insert(&Person{"John", 19})
	l.insert(&Person{"Bob", 19})
	l.insert(&Person{"Jack", 19})
	l.insert(&Person{"Martin", 19})

	l.remove()
	
	l.display()

}

type Person struct {
	name string
	age int
}

var p = Person{"",3}

type Node struct {
	data *Person
	next *Node
}

type LinkedList struct {
	head *Node
	current *Node
}

func (l *LinkedList) isEmpty() bool {
	return l.head == nil
} 

func (l *LinkedList) findNext(){
	l.current = l.current.next
}

func (l *LinkedList) insert(val *Person){
	if l.head == nil {
		l.current = &Node{val,nil}	
		l.head = l.current
	} else {
		tmp:= l.current.next
		
		n:= Node{val, tmp}
		
		l.current.next = &n

		l.current = l.current.next
		
	}

}

func (l *LinkedList) remove() {
	if l.current == l.head {
		l.head = l.head.next
	} else {
        	temp:= l.head
        	for temp.next != l.current {
                	temp = temp.next
        	}
		temp.next = l.current.next
	}
	if l.current.next == nil {
		l.current = l.head 
	}else{
		l.current = l.current.next
	}

}

func (l *LinkedList) display(){
	p:= l.head
	for p != nil {
		fmt.Printf("%v -> ", p.data)
		
		p = p.next
	}
	fmt.Println()
}

Stack (Array-based)

package main 

import (
	"fmt"
	"errors"
	"log"
)

func Check(err error) {
	if err != nil {
		log.Fatal(err)
	}
	
}

type Stack [] string

func main (){

	var stack Stack

	stack.Push("John Wick")
	stack.Push("Spiderman")
	stack.Push("Mary Jane")
	stack.Push("Superman")

	stack.Display()

  item ,err:=stack.peek()
  Check(err)
  fmt.Println("Peek Item value: ", item)
  
	item1, err :=stack.Pop()
	Check(err)

	fmt.Println("Item1 value: ", item1)

	stack.Display()

	item2, err :=stack.Pop()
	Check(err)

	fmt.Println("Item2 value: ", item2)

	item3,err :=stack.Pop()

	Check(err)
	fmt.Println("Item3 value: ", item3)

	// Empty stack : This will throw an error
	item4,err :=stack.Pop() 
	Check(err)
	
	fmt.Println("Item4 value: ", item4)

	// Display the stack items
	stack.Display()

}

func (stack *Stack) Pop () (string, error){
	 
  stack.isEmpty()	

	item := (*stack)[len(*stack) - 1]

	*stack = (*stack)[:len(*stack) - 1]
	fmt.Println("Item has been popped out successfully")

	return item, nil
}

func (stack *Stack) Push(item string) {

	*stack = append(*stack, item)

	fmt.Println("Item has been pushed successfully")
}

func (stack *Stack) Display(){

	for i, item := range *stack {
		fmt.Printf("[%d] : %s\n", i, item)
	}
	
}

func (stack *Stack) isEmpty() {
  if len(*stack) == 0 {
		errors.New("The stack is empty")
	}  
}

func (stack *Stack) peek()(string, error) {
  stack.isEmpty()
	item := (*stack)[len(*stack) - 1]
  return item, nil
}

Stack (linked-list based)

Binary Tree

package main

import "fmt"

const  (
  PreOrder  = "preOrder"
  InOrder  = "inOrder"
  PostOrder = "postOrder"
  Root = "root"
  LeftChild = "leftChild"
  RightChild = "rightChild"
  Parent = "parent"
)

type node struct {
  data int 
  left *node
  right *node
}

type binaryTree struct {
  root *node 
  current *node
}

func main(){
    var bt binaryTree = binaryTree{nil, nil}
    
    bt.insert(90, Root)
    fmt.Println(bt.current)
    bt.insert(20, RightChild)
    bt.find(Parent)
    bt.insert(16, LeftChild)
    bt.find(Parent)
  
    fmt.Println(bt.current)

    bt.find(LeftChild)
    
    bt.deleteSubTree()

    fmt.Println(bt.current)
}

func (bt *binaryTree) insert(data int, relative string ) bool {
  switch relative {
    case Root:
      if !bt.isTreeEmpty() {
        return false
      }
      n := node{data,nil,nil}
      bt.root = &n
      bt.current = bt.root
      return true
    case Parent:{
      // You can't find the parent of the root
      if bt.current == bt.root {
        return false 
      }
      bt.current = findParent(bt.current, bt.root)
      return true
    }
    case LeftChild:
      if bt.current.left != nil {
        return false
      }
      n := node{data, nil, nil}
      bt.current.left = &n
      bt.current = bt.current.left
      return true
    case RightChild:
      if bt.current.right != nil {
        return false
      }
      n := node{data, nil, nil}
      bt.current.right = &n
      bt.current = bt.current.right
      return true
    default:
      return false
  }
}

func (bt *binaryTree) deleteSubTree() {
  if bt.current == bt.root {
    bt.root = nil
    bt.current = bt.root
  } else {
    n := bt.current
    bt.find(Parent)
    if(bt.current.left == n){
      bt.current.left = nil
    } else if (bt.current.right == n){
      bt.current.right = nil
    }
    bt.current = bt.root
  }
  
}

func (bt *binaryTree) update(data int){
  bt.current.data = data
}

func (bt *binaryTree) retrieve(data int) *node{
  return bt.current
}

func  (bt *binaryTree) find(relative string)bool{
  switch relative{
    case Root :{
      bt.current = bt.root
      return true
    }
    case Parent:{
      if bt.current == bt.root {
        return false
      }
      bt.current = findParent(bt.current, bt.root)
      return true
    }
    case LeftChild:{
      if bt.current.left == nil {
        return false
      }
      bt.current  = bt.current.left
      return true
    }
    case RightChild:{
      if bt.current.right == nil {
        return false
      }
      bt.current  = bt.current.right
      return true
    }
    default:{
      return false
    }
  }

}

func findParent (n *node, root *node)*node{
  if root == nil {
    return nil
  }
  if root.right == nil && root.left == nil {
    return nil
  } else if root.right == n || root.left == n {
      return root
  }else {
    tmp:= findParent(n, root.right)
    if tmp != nil {
      return tmp.left
    }else {
      return findParent(n, root.left)
    }
  }
} 

func (bt *binaryTree) isTreeEmpty() bool {
  return bt.root == nil
}

Queue

package main
import "fmt"

type node struct {
  data int 
  next *node
}

type queue struct {
  head *node
  tail *node
  size int
}

func main(){
  q:= queue{nil,nil,10}
  fmt.Println(q)

  q.enqueue(10)
  q.enqueue(20)
  q.enqueue(0)

  fmt.Println(*q.find(10))

  q.display()
} 

func (q *queue) enqueue(data int){
  n:= node{data, nil}
  if q.head == nil {
    q.head = &n
    q.tail = &n
  }else {  
    q.tail.next = &n
    q.tail = q.tail.next
  }
  q.size++
}

func (q *queue) dequeue () int {
  data := q.head.data
  q.head = q.head.next
  q.size--
  if q.size == 0 {
    q.tail = nil
  }
  return data
}

func (q *queue) find(data int) *node{
  tmp := q.head

  for tmp != nil {
    if tmp.data == data {
      return tmp
    }
    tmp = tmp.next
  }
  return nil
}

func (q *queue) display(){
  tmp := q.head
  for tmp.next != nil {
    fmt.Print(tmp.data ," --> ")
    tmp = tmp.next
  }
  if &tmp != nil {
    fmt.Print(tmp.data )
  }
}

Ring Buffer (Circular Queue)

type MyCircularQueue struct {
    size int
    head int
    queue []int
}

func Constructor(k int) MyCircularQueue {
    queue := make([]int, k)
    size := 0
    head := 0
    
    return MyCircularQueue{
        queue:queue,
        size:size,
        head:head,
    }
}

func (this *MyCircularQueue) EnQueue(value int) bool {
    if this.IsFull(){
        return false
    }
    
    this.queue[(this.head + this.size) % cap(this.queue)] = value
    
    this.size++
    
    return true
}

func (this *MyCircularQueue) DeQueue() bool {
    if this.IsEmpty(){
        return false
    }
    
    this.head = (this.head+1) % cap(this.queue)
   
    this.size--
    return true
}

func (this *MyCircularQueue) Front() int {
    if this.IsEmpty(){
        return -1
    }
    return this.queue[this.head]   
}

func (this *MyCircularQueue) Rear() int {
     if this.IsEmpty(){
        return -1
    }
    return this.queue[(this.head + this.size -1) % cap(this.queue)] 
}

func (this *MyCircularQueue) IsEmpty() bool {
    return this.size == 0
}

func (this *MyCircularQueue) IsFull() bool {
    return this.size == cap(this.queue)
}

/**
 * Your MyCircularQueue object will be instantiated and called as such:
 * obj := Constructor(k);
 * param_1 := obj.EnQueue(value);
 * param_2 := obj.DeQueue();
 * param_3 := obj.Front();
 * param_4 := obj.Rear();
 * param_5 := obj.IsEmpty();
 * param_6 := obj.IsFull();
 */

Last updated