├── go.mod ├── README.md ├── graph ├── graph_test.go └── graph.go ├── stack ├── stack_test.go └── stack.go ├── queue ├── queue_test.go └── queue.go ├── tree ├── tree_test.go └── tree.go ├── linkedlist ├── linkedlist_test.go └── linkedlist.go ├── hashtable ├── hashtable_test.go └── hashtable.go ├── maxheap ├── maxheap_test.go └── maxheap.go ├── minheap ├── minheap_test.go └── minheap.go └── heap └── heap.go /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/dorin131/go-data-structures 2 | 3 | go 1.13 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-data-structures 2 | 3 | An implementation in Go of the following data structures: 4 | 5 | - Linked List 6 | - Stack 7 | - Queue 8 | - Binary Search Tree 9 | - Graph 10 | - Hash Table 11 | - Min Heap 12 | - Max heap -------------------------------------------------------------------------------- /graph/graph_test.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func ExampleGraph() { 8 | graph := New() 9 | node0 := graph.AddNode() 10 | node1 := graph.AddNode() 11 | node2 := graph.AddNode() 12 | 13 | graph.AddEdge(node0, node1, 1) 14 | 15 | fmt.Println(node0) 16 | fmt.Println(node1) 17 | fmt.Println(node2) 18 | fmt.Println(graph.Nodes()) 19 | graph.AddEdge(node0, node2, 5) 20 | graph.Neighbors(node0) 21 | // Output: 22 | // 0 23 | // 1 24 | // 2 25 | // [0 1 2] 26 | } 27 | -------------------------------------------------------------------------------- /stack/stack_test.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func ExampleStack() { 8 | stack := New() 9 | peekResult, _ := stack.Push(1).Push(2).Peek() 10 | fmt.Println(peekResult) 11 | popResult, _ := stack.Pop() 12 | fmt.Println(popResult) 13 | fmt.Println(stack.IsEmpty()) 14 | popResult, _ = stack.Pop() 15 | fmt.Println(popResult) 16 | fmt.Println(stack.IsEmpty()) 17 | _, err := stack.Pop() 18 | fmt.Println(err) 19 | // Output: 20 | // 2 21 | // 2 22 | // false 23 | // 1 24 | // true 25 | // Stack is empty 26 | } 27 | -------------------------------------------------------------------------------- /queue/queue_test.go: -------------------------------------------------------------------------------- 1 | package queue 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func ExampleQueue() { 8 | queue := New() 9 | result, _ := queue.Enqueue(1).Enqueue(2).Enqueue(3).Peek() 10 | fmt.Println(result) 11 | fmt.Println(queue.IsEmpty()) 12 | result, _ = queue.Dequeue() 13 | fmt.Println(result) 14 | result, _ = queue.Dequeue() 15 | fmt.Println(result) 16 | queue.Dequeue() 17 | fmt.Println(queue.IsEmpty()) 18 | _, err := queue.Peek() 19 | fmt.Println(err) 20 | // Output: 21 | // 1 22 | // false 23 | // 1 24 | // 2 25 | // true 26 | // Queue is empty 27 | } 28 | -------------------------------------------------------------------------------- /tree/tree_test.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | import "fmt" 4 | 5 | func ExampleTreeInsert() { 6 | tree := New(5) 7 | 8 | tree.Insert(3).Insert(8).Insert(-5).Insert(200).Traverse() 9 | // Output: 10 | // -5 11 | // 3 12 | // 5 13 | // 8 14 | // 200 15 | } 16 | 17 | func ExampleTreeContains() { 18 | tree := New(5) 19 | 20 | tree.Insert(3).Insert(8).Insert(-5).Insert(200) 21 | 22 | fmt.Println(tree.Contains(5)) 23 | // Output: 24 | // true 25 | } 26 | 27 | func ExampleTreeDoesntContain() { 28 | tree := New(5) 29 | 30 | tree.Insert(3).Insert(8).Insert(-5).Insert(200) 31 | 32 | fmt.Println(tree.Contains(0)) 33 | // Output: 34 | // false 35 | } 36 | -------------------------------------------------------------------------------- /linkedlist/linkedlist_test.go: -------------------------------------------------------------------------------- 1 | package linkedlist 2 | 3 | func ExampleNew() { 4 | linkedList := New() 5 | linkedList.Append(1).Append(2).Append(3).PrintAll() 6 | // Output: 7 | // 1 8 | // 2 9 | // 3 10 | } 11 | 12 | func ExampleNewWithDeletion() { 13 | linkedList := New() 14 | linkedList.Append(1).Append(2).Append(3).DeleteWithValue(2).PrintAll() 15 | // Output: 16 | // 1 17 | // 3 18 | } 19 | 20 | func ExampleNewWithDeletionOfHead() { 21 | linkedList := New() 22 | linkedList.Append(1).Append(2).Append(3).DeleteWithValue(1).PrintAll() 23 | // Output: 24 | // 2 25 | // 3 26 | } 27 | 28 | func ExampleNewWithDeletionOfTail() { 29 | linkedList := New() 30 | linkedList.Append(1).Append(2).Append(3).DeleteWithValue(3).PrintAll() 31 | // Output: 32 | // 1 33 | // 2 34 | } 35 | -------------------------------------------------------------------------------- /hashtable/hashtable_test.go: -------------------------------------------------------------------------------- 1 | package hashtable 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestHashTableSetGet(t *testing.T) { 8 | var h *HashTable 9 | testCases := []struct { 10 | key string 11 | value string 12 | }{ 13 | {"Dorin", "Great"}, 14 | {"SomeKey", "SomeValue"}, 15 | {"SomeKey", "SomeOtherValue"}, 16 | {"__", "%"}, 17 | {" ", ""}, 18 | {"", " "}, 19 | {"", ""}, 20 | } 21 | 22 | for i, test := range testCases { 23 | h = New() 24 | h.Set(test.key, test.value) 25 | result, ok := h.Get(test.key) 26 | if !ok { 27 | t.Errorf("[%d]: Could not get value from key \"%s\"", i, test.key) 28 | } 29 | if result != test.value { 30 | t.Errorf( 31 | "[%d]: Incorrect value for key \"%s\", got = \"%s\", expected = \"%s\"", 32 | i, test.key, result, test.value, 33 | ) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /queue/queue.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package queue provides a slice-based Queue data structure 3 | */ 4 | package queue 5 | 6 | import "fmt" 7 | 8 | // Queue : data structure 9 | type Queue struct { 10 | data []int 11 | } 12 | 13 | // New : returns a new instance of a Queue 14 | func New() *Queue { 15 | return &Queue{ 16 | data: []int{}, 17 | } 18 | } 19 | 20 | // IsEmpty : checks whether the queue is empty 21 | func (q *Queue) IsEmpty() bool { 22 | return len(q.data) == 0 23 | } 24 | 25 | // Peek : return the next element in the queue 26 | func (q *Queue) Peek() (int, error) { 27 | if len(q.data) == 0 { 28 | return 0, fmt.Errorf("Queue is empty") 29 | } 30 | return q.data[0], nil 31 | } 32 | 33 | // Enqueue : adds an element onto the queue 34 | func (q *Queue) Enqueue(n int) *Queue { 35 | q.data = append(q.data, n) 36 | return q 37 | } 38 | 39 | // Dequeue : removes the next element from the queue 40 | // and returns its value 41 | func (q *Queue) Dequeue() (int, error) { 42 | if len(q.data) == 0 { 43 | return 0, fmt.Errorf("Queue is empty") 44 | } 45 | element := q.data[0] 46 | q.data = q.data[1:] 47 | return element, nil 48 | } 49 | -------------------------------------------------------------------------------- /stack/stack.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package stack provides a slice-based Stack data structure 3 | */ 4 | package stack 5 | 6 | import "fmt" 7 | 8 | // Stack : data structure 9 | type Stack struct { 10 | data []int 11 | } 12 | 13 | // New : returns a new instance of a stack 14 | func New() *Stack { 15 | return &Stack{ 16 | data: []int{}, 17 | } 18 | } 19 | 20 | // IsEmpty : will return a boolean indicating whether there 21 | // are any elements on the stack 22 | func (s *Stack) IsEmpty() bool { 23 | return len(s.data) == 0 24 | } 25 | 26 | // Peek : will return the element on the top of the stack 27 | func (s *Stack) Peek() (int, error) { 28 | if s.IsEmpty() { 29 | return 0, fmt.Errorf("Stack is empty") 30 | } 31 | return s.data[len(s.data)-1], nil 32 | } 33 | 34 | // Push : Adds an element on the stack 35 | func (s *Stack) Push(n int) *Stack { 36 | s.data = append(s.data, n) 37 | return s 38 | } 39 | 40 | // Pop : removes an element from the stack and returns 41 | // its value 42 | func (s *Stack) Pop() (int, error) { 43 | if len(s.data) == 0 { 44 | return 0, fmt.Errorf("Stack is empty") 45 | } 46 | element := s.data[len(s.data)-1] 47 | s.data = s.data[:len(s.data)-1] 48 | return element, nil 49 | } 50 | -------------------------------------------------------------------------------- /tree/tree.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package tree provides a Tree data structure (Binary Search Tree) 3 | We assume that every value is of type "int" and is unique 4 | */ 5 | package tree 6 | 7 | import ( 8 | "fmt" 9 | ) 10 | 11 | // Node : represents a single node of a Tree data structure 12 | type Node struct { 13 | Left *Node 14 | Right *Node 15 | Data int 16 | } 17 | 18 | // New : constructor function for a Tree node 19 | func New(data int) *Node { 20 | return &Node{ 21 | Left: nil, 22 | Right: nil, 23 | Data: data, 24 | } 25 | } 26 | 27 | // Insert : adds a node to the tree 28 | func (t *Node) Insert(data int) *Node { 29 | if data < t.Data { 30 | if t.Left != nil { 31 | t.Left.Insert(data) 32 | } else { 33 | t.Left = New(data) 34 | } 35 | } else { 36 | if t.Right != nil { 37 | t.Right.Insert(data) 38 | } else { 39 | t.Right = New(data) 40 | } 41 | } 42 | return t 43 | } 44 | 45 | // Contains : checks if the tree contains a node with a given value 46 | func (t *Node) Contains(data int) bool { 47 | if t.Data == data { 48 | return true 49 | } 50 | if data < t.Data { 51 | if t.Left != nil { 52 | return t.Left.Contains(data) 53 | } else { 54 | return false 55 | } 56 | } else { 57 | if t.Right != nil { 58 | return t.Right.Contains(data) 59 | } else { 60 | return false 61 | } 62 | } 63 | return false 64 | } 65 | 66 | // Traverse : prints all elements of the tree 67 | func (t *Node) Traverse() { 68 | if t.Left != nil { 69 | t.Left.Traverse() 70 | } 71 | fmt.Println(t.Data) 72 | if t.Right != nil { 73 | t.Right.Traverse() 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /maxheap/maxheap_test.go: -------------------------------------------------------------------------------- 1 | package maxheap 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | "testing" 7 | ) 8 | 9 | func ExampleMaxHeap() { 10 | h := New([]int{100, 500}) 11 | h.Insert(333).Insert(-3).Insert(0).Insert(1000).Insert(-44).Insert(5) 12 | fmt.Println(h.ExtractMax()) 13 | // Output: 14 | // 1000 15 | } 16 | 17 | func TestMinHeap(t *testing.T) { 18 | tests := []struct { 19 | initial []int 20 | toAdd []int 21 | }{ 22 | {[]int{}, []int{4, 9, 10, 0, -4, 7}}, 23 | {[]int{}, []int{1, 2, 3, 4, 5}}, 24 | {[]int{}, []int{300, 5, 77, -8, 0, 50}}, 25 | {[]int{}, []int{-1000, 1000}}, 26 | {[]int{}, []int{1000, -1000}}, 27 | {[]int{4, 9, 10, 0, -4, 7}, []int{}}, 28 | {[]int{0, 7, 10}, []int{1, 2, 3, 4, 5}}, 29 | {[]int{100}, []int{300, 5, 77, -8, 0, 50}}, 30 | {[]int{-2000, 0, 800}, []int{-1000, 1000}}, 31 | {[]int{5000, 10000}, []int{1000, -1000}}, 32 | } 33 | for i, test := range tests { 34 | h := New(test.initial) 35 | for _, n := range test.toAdd { 36 | h.Insert(n) 37 | } 38 | 39 | checkMaxHeap(i, h, t) 40 | } 41 | } 42 | 43 | func checkMaxHeap(n int, h *MaxHeap, t *testing.T) { 44 | result := []int{} 45 | correctlySorted := make([]int, len(h.Items)) 46 | copy(correctlySorted, h.Items) 47 | 48 | length := len(h.Items) 49 | for i := 0; i < length; i++ { 50 | result = append(result, h.ExtractMax()) 51 | } 52 | sort.Slice(correctlySorted, func(i, j int) bool { 53 | return correctlySorted[i] > correctlySorted[j] 54 | }) 55 | 56 | for k := range correctlySorted { 57 | if correctlySorted[k] != result[k] { 58 | t.Errorf("[%v] Expected: %v, Got: %v\n", n, correctlySorted, result) 59 | return 60 | } 61 | } 62 | fmt.Printf("[%v] Correctly sorted: %v\n", n, result) 63 | } 64 | -------------------------------------------------------------------------------- /minheap/minheap_test.go: -------------------------------------------------------------------------------- 1 | package minheap 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | "testing" 7 | ) 8 | 9 | func ExampleMinHeap() { 10 | h := New([]int{100, 500}) 11 | h.Insert(333).Insert(-3).Insert(0).Insert(1000).Insert(-44).Insert(5) 12 | fmt.Println(h.ExtractMin()) 13 | // Output: 14 | // -44 15 | } 16 | 17 | func TestMinHeap(t *testing.T) { 18 | tests := []struct { 19 | initial []int 20 | toAdd []int 21 | }{ 22 | {[]int{}, []int{4, 9, 10, 0, -4, 7}}, 23 | {[]int{}, []int{1, 2, 3, 4, 5}}, 24 | {[]int{}, []int{300, 5, 77, -8, 0, 50}}, 25 | {[]int{}, []int{-1000, 1000}}, 26 | {[]int{}, []int{1000, -1000}}, 27 | {[]int{4, 9, 10, 0, -4, 7}, []int{}}, 28 | {[]int{0, 7, 10}, []int{1, 2, 3, 4, 5}}, 29 | {[]int{100}, []int{300, 5, 77, -8, 0, 50}}, 30 | {[]int{-2000, 0, 800}, []int{-1000, 1000}}, 31 | {[]int{5000, 10000}, []int{1000, -1000}}, 32 | } 33 | for i, test := range tests { 34 | h := New(test.initial) 35 | for _, n := range test.toAdd { 36 | h.Insert(n) 37 | } 38 | 39 | checkMinHeap(i, h, t) 40 | } 41 | } 42 | 43 | func checkMinHeap(n int, h *MinHeap, t *testing.T) { 44 | result := []int{} 45 | correctlySorted := make([]int, len(h.Items)) 46 | copy(correctlySorted, h.Items) 47 | 48 | length := len(h.Items) 49 | for i := 0; i < length; i++ { 50 | result = append(result, h.ExtractMin()) 51 | } 52 | sort.Slice(correctlySorted, func(i, j int) bool { 53 | return correctlySorted[i] < correctlySorted[j] 54 | }) 55 | 56 | for k := range correctlySorted { 57 | if correctlySorted[k] != result[k] { 58 | t.Errorf("[%v] Expected: %v, Got: %v\n", n, correctlySorted, result) 59 | return 60 | } 61 | } 62 | fmt.Printf("[%v] Correctly sorted: %v\n", n, result) 63 | } 64 | -------------------------------------------------------------------------------- /graph/graph.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package graph provides a Graph data structure (directed & weighted) 3 | */ 4 | package graph 5 | 6 | // Graph : represents a Graph 7 | type Graph struct { 8 | nodes []*GraphNode 9 | } 10 | 11 | // GraphNode : represents a Graph node 12 | type GraphNode struct { 13 | id int 14 | edges map[int]int 15 | } 16 | 17 | // New : returns a new instance of a Graph 18 | func New() *Graph { 19 | return &Graph{ 20 | nodes: []*GraphNode{}, 21 | } 22 | } 23 | 24 | // AddNode : adds a new node to the Graph 25 | func (g *Graph) AddNode() (id int) { 26 | id = len(g.nodes) 27 | g.nodes = append(g.nodes, &GraphNode{ 28 | id: id, 29 | edges: make(map[int]int), 30 | }) 31 | return 32 | } 33 | 34 | // AddEdge : adds a directional edge together with a weight 35 | func (g *Graph) AddEdge(n1, n2 int, w int) { 36 | g.nodes[n1].edges[n2] = w 37 | } 38 | 39 | // Neighbors : returns a list of node IDs that are linked to this node 40 | func (g *Graph) Neighbors(id int) []int { 41 | neighbors := []int{} 42 | for _, node := range g.nodes { 43 | for edge := range node.edges { 44 | if node.id == id { 45 | neighbors = append(neighbors, edge) 46 | } 47 | if edge == id { 48 | neighbors = append(neighbors, node.id) 49 | } 50 | } 51 | } 52 | return neighbors 53 | } 54 | 55 | // Nodes : returns a list of node IDs 56 | func (g *Graph) Nodes() []int { 57 | nodes := make([]int, len(g.nodes)) 58 | for i := range g.nodes { 59 | nodes[i] = i 60 | } 61 | return nodes 62 | } 63 | 64 | // Edges : returns a list of edges with weights 65 | func (g *Graph) Edges() [][3]int { 66 | edges := make([][3]int, 0, len(g.nodes)) 67 | for i := range g.nodes { 68 | for k, v := range g.nodes[i].edges { 69 | edges = append(edges, [3]int{i, k, int(v)}) 70 | } 71 | } 72 | return edges 73 | } 74 | -------------------------------------------------------------------------------- /linkedlist/linkedlist.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package linkedlist provides a Linked List data structure 3 | */ 4 | package linkedlist 5 | 6 | import "fmt" 7 | 8 | // LinkedList : Data structure 9 | type LinkedList struct { 10 | Head *Node 11 | Tail *Node 12 | } 13 | 14 | // Node : A Linked List node 15 | type Node struct { 16 | Next *Node 17 | Data interface{} 18 | } 19 | 20 | // New : Create a new Linked List 21 | func New() *LinkedList { 22 | emptyNode := &Node{ 23 | Next: nil, 24 | Data: nil, 25 | } 26 | return &LinkedList{ 27 | Head: emptyNode, 28 | Tail: emptyNode, 29 | } 30 | } 31 | 32 | // IsEmpty : check if there are any elements in the list 33 | func (ll *LinkedList) IsEmpty() bool { 34 | if ll.Head == nil { 35 | return true 36 | } 37 | return false 38 | } 39 | 40 | // Append : Appending a new node to the end of the Linked List 41 | func (ll *LinkedList) Append(d interface{}) *LinkedList { 42 | nextNode := &Node{ 43 | Next: nil, 44 | Data: d, 45 | } 46 | if ll.Head.Data == nil { 47 | ll.Head = nextNode 48 | } else { 49 | ll.Tail.Next = nextNode 50 | } 51 | ll.Tail = nextNode 52 | return ll 53 | } 54 | 55 | // DeleteWithValue : Deletes node which has a specific value 56 | func (ll *LinkedList) DeleteWithValue(v interface{}) *LinkedList { 57 | var node = ll.Head 58 | if node.Data == v { 59 | ll.Head = ll.Head.Next 60 | return ll 61 | } 62 | for { 63 | if v == node.Next.Data { 64 | if node.Next.Next != nil { 65 | node.Next = node.Next.Next 66 | break 67 | } 68 | node.Next = nil 69 | break 70 | } 71 | node = node.Next 72 | } 73 | return ll 74 | } 75 | 76 | // PrintAll : Prints all elements of the Linked List 77 | func (ll *LinkedList) PrintAll() { 78 | var node = ll.Head 79 | for { 80 | fmt.Println(node.Data) 81 | if node.Next == nil { 82 | return 83 | } 84 | node = node.Next 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /heap/heap.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package heap provides helper methods for a Min Heap or a Max Heap 3 | Not to be used on its own. 4 | */ 5 | package heap 6 | 7 | // Heap : contains a slice which holds the underlying heap data 8 | type Heap struct { // the total number of elements, which doesn't go down on extract 9 | Items []int 10 | } 11 | 12 | // GetLeftIndex : get left index of a Heap node 13 | func (h *Heap) GetLeftIndex(parentIndex int) int { 14 | return 2*parentIndex + 1 15 | } 16 | 17 | // GetRightIndex : get right index of a Heap node 18 | func (h *Heap) GetRightIndex(parentIndex int) int { 19 | return 2*parentIndex + 2 20 | } 21 | 22 | // GetParentIndex : get parent index of a Heap node 23 | func (h *Heap) GetParentIndex(childIndex int) int { 24 | return (childIndex - 1) / 2 25 | } 26 | 27 | // HasLeft : check if node at index has left node 28 | func (h *Heap) HasLeft(index int) bool { 29 | return h.GetLeftIndex(index) < len(h.Items) 30 | } 31 | 32 | // HasRight : check if node at index has right node 33 | func (h *Heap) HasRight(index int) bool { 34 | return h.GetRightIndex(index) < len(h.Items) 35 | } 36 | 37 | // HasParent : check if node at index has parent node 38 | func (h *Heap) HasParent(index int) bool { 39 | return h.GetParentIndex(index) >= 0 40 | } 41 | 42 | // Left : get left node value, given an index 43 | func (h *Heap) Left(index int) int { 44 | return h.Items[h.GetLeftIndex(index)] 45 | } 46 | 47 | // Right : get right node value, given an index 48 | func (h *Heap) Right(index int) int { 49 | return h.Items[h.GetRightIndex(index)] 50 | } 51 | 52 | // Parent : get parent node value, given an index 53 | func (h *Heap) Parent(index int) int { 54 | return h.Items[h.GetParentIndex(index)] 55 | } 56 | 57 | // Swap : swap values of two nodes at specified indeces 58 | func (h *Heap) Swap(indexOne, indexTwo int) { 59 | h.Items[indexOne], h.Items[indexTwo] = h.Items[indexTwo], h.Items[indexOne] 60 | } 61 | -------------------------------------------------------------------------------- /hashtable/hashtable.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package hashtable provides a Hash Table 3 | */ 4 | package hashtable 5 | 6 | import ( 7 | "math" 8 | 9 | "github.com/dorin131/go-data-structures/linkedlist" 10 | ) 11 | 12 | const arrayLength = 100 13 | 14 | // HashTable : a hash table data structure 15 | type HashTable struct { 16 | data [arrayLength]*linkedlist.LinkedList 17 | } 18 | 19 | type listData struct { 20 | key string 21 | value interface{} 22 | } 23 | 24 | // New : a hash table constructor 25 | func New() *HashTable { 26 | return &HashTable{ 27 | [arrayLength]*linkedlist.LinkedList{}, 28 | } 29 | } 30 | 31 | func hash(s string) int { 32 | h := 0 33 | // char[0] * 31^n-1 + char[1] * 31^n-2 + ... + char[n-1] 34 | for pos, char := range s { 35 | h += int(char) * int(math.Pow(31, float64(len(s)-pos+1))) 36 | } 37 | return h 38 | } 39 | 40 | func index(hash int) int { 41 | return hash % arrayLength 42 | } 43 | 44 | // Set : set a key and value 45 | func (h *HashTable) Set(k string, v interface{}) *HashTable { 46 | index := index(hash(k)) 47 | 48 | if h.data[index] == nil { 49 | h.data[index] = linkedlist.New() 50 | h.data[index].Append(listData{k, v}) 51 | } else { 52 | node := h.data[index].Head 53 | for { 54 | if node != nil { 55 | d := node.Data.(listData) 56 | if d.key == k { 57 | d.value = v 58 | break 59 | } 60 | } else { 61 | h.data[index].Append(listData{k, v}) 62 | break 63 | } 64 | node = node.Next 65 | } 66 | } 67 | return h 68 | } 69 | 70 | // Get : get a value by key 71 | func (h *HashTable) Get(k string) (result interface{}, ok bool) { 72 | index := index(hash(k)) 73 | linkedList := h.data[index] 74 | 75 | if linkedList == nil { 76 | return "", false 77 | } 78 | node := linkedList.Head 79 | for { 80 | if node != nil { 81 | d := node.Data.(listData) 82 | if d.key == k { 83 | return d.value, true 84 | } 85 | } else { 86 | return "", false 87 | } 88 | node = node.Next 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /maxheap/maxheap.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package maxheap provides a Max Heap data structure 3 | */ 4 | package maxheap 5 | 6 | import ( 7 | "log" 8 | 9 | "github.com/dorin131/go-data-structures/heap" 10 | ) 11 | 12 | // MaxHeap : represents a Max heap data structure 13 | type MaxHeap struct { 14 | *heap.Heap 15 | } 16 | 17 | // New : returns a new instance of a Heap 18 | func New(input []int) *MaxHeap { 19 | h := &MaxHeap{ 20 | &heap.Heap{ 21 | Items: input, 22 | }, 23 | } 24 | 25 | if len(h.Items) > 0 { 26 | h.buildMaxHeap() 27 | } 28 | 29 | return h 30 | } 31 | 32 | func (h *MaxHeap) buildMaxHeap() { 33 | for i := len(h.Items)/2 - 1; i >= 0; i-- { 34 | h.maxHeapifyDown(i) 35 | } 36 | } 37 | 38 | // Insert : adds an element to the heap 39 | func (h *MaxHeap) Insert(item int) *MaxHeap { 40 | h.Items = append(h.Items, item) 41 | lastElementIndex := len(h.Items) - 1 42 | h.maxHeapifyUp(lastElementIndex) 43 | 44 | return h 45 | } 46 | 47 | // ExtractMax : returns the maximum element and removes it from the Heap 48 | func (h *MaxHeap) ExtractMax() int { 49 | if len(h.Items) == 0 { 50 | log.Fatal("No items in the heap") 51 | } 52 | minItem := h.Items[0] 53 | lastIndex := len(h.Items) - 1 54 | h.Items[0] = h.Items[lastIndex] 55 | 56 | // shrinking slice 57 | h.Items = h.Items[:len(h.Items)-1] 58 | 59 | h.maxHeapifyDown(0) 60 | 61 | return minItem 62 | } 63 | 64 | func (h *MaxHeap) maxHeapifyUp(index int) { 65 | for h.HasParent(index) && h.Parent(index) < h.Items[index] { 66 | h.Swap(h.GetParentIndex(index), index) 67 | index = h.GetParentIndex(index) 68 | } 69 | } 70 | 71 | func (h *MaxHeap) maxHeapifyDown(index int) { 72 | // iterate until we have a child node smaller than the index value 73 | for (h.HasLeft(index) && h.Items[index] < h.Left(index)) || 74 | (h.HasRight(index) && h.Items[index] < h.Right(index)) { 75 | // if both children are smaller 76 | if (h.HasLeft(index) && h.Items[index] < h.Left(index)) && 77 | (h.HasRight(index) && h.Items[index] < h.Right(index)) { 78 | // compare the children and swap with the largest 79 | if h.Left(index) > h.Right(index) { 80 | h.Swap(index, h.GetLeftIndex(index)) 81 | index = h.GetLeftIndex(index) 82 | } else { 83 | h.Swap(index, h.GetRightIndex(index)) 84 | index = h.GetRightIndex(index) 85 | } 86 | // else if only left child is smaller than swap with it 87 | } else if h.HasLeft(index) && h.Items[index] < h.Left(index) { 88 | h.Swap(index, h.GetLeftIndex(index)) 89 | index = h.GetLeftIndex(index) 90 | // else it must be the right child that is smaller, so we swap with it 91 | } else { 92 | h.Swap(index, h.GetRightIndex(index)) 93 | index = h.GetRightIndex(index) 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /minheap/minheap.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package minheap provides an implementation of a Min Heap data structure 3 | */ 4 | package minheap 5 | 6 | import ( 7 | "log" 8 | 9 | "github.com/dorin131/go-data-structures/heap" 10 | ) 11 | 12 | // MinHeap : represents a Min Heap data structure 13 | type MinHeap struct { 14 | *heap.Heap 15 | } 16 | 17 | // New : returns a new instance of a Heap 18 | func New(input []int) *MinHeap { 19 | h := &MinHeap{ 20 | &heap.Heap{ 21 | Items: input, 22 | }, 23 | } 24 | 25 | if len(h.Items) > 0 { 26 | h.buildMinHeap() 27 | } 28 | 29 | return h 30 | } 31 | 32 | // ExtractMin : removes top element of the heap and returns it 33 | func (h *MinHeap) ExtractMin() int { 34 | if len(h.Items) == 0 { 35 | log.Fatal("No items in the heap") 36 | } 37 | minItem := h.Items[0] 38 | lastIndex := len(h.Items) - 1 39 | h.Items[0] = h.Items[lastIndex] 40 | 41 | // shrinking slice 42 | h.Items = h.Items[:len(h.Items)-1] 43 | 44 | h.minHeapifyDown(0) 45 | 46 | return minItem 47 | } 48 | 49 | // Insert : adds a new element to the heap 50 | func (h *MinHeap) Insert(item int) *MinHeap { 51 | h.Items = append(h.Items, item) 52 | lastElementIndex := len(h.Items) - 1 53 | h.minHeapifyUp(lastElementIndex) 54 | 55 | return h 56 | } 57 | 58 | // buildMinHeap : given a slice, arrange the elements so that 59 | // they satisfy the Min Heap properties 60 | func (h *MinHeap) buildMinHeap() { 61 | for i := len(h.Items)/2 - 1; i >= 0; i-- { 62 | h.minHeapifyDown(i) 63 | } 64 | } 65 | 66 | // minHeapifyDown : takes the top element and moves it down until 67 | // the Min Heap properties are satisfied 68 | func (h *MinHeap) minHeapifyDown(index int) { 69 | for (h.HasLeft(index) && (h.Items[index] > h.Left(index))) || 70 | (h.HasRight(index) && (h.Items[index] > h.Right(index))) { 71 | if (h.HasLeft(index) && (h.Items[index] > h.Left(index))) && 72 | (h.HasRight(index) && (h.Items[index] > h.Right(index))) { 73 | if h.Left(index) < h.Right(index) { 74 | h.Swap(index, h.GetLeftIndex(index)) 75 | index = h.GetLeftIndex(index) 76 | } else { 77 | h.Swap(index, h.GetRightIndex(index)) 78 | index = h.GetRightIndex(index) 79 | } 80 | } else if h.HasLeft(index) && (h.Items[index] > h.Left(index)) { 81 | h.Swap(index, h.GetLeftIndex(index)) 82 | index = h.GetLeftIndex(index) 83 | } else { 84 | h.Swap(index, h.GetRightIndex(index)) 85 | index = h.GetRightIndex(index) 86 | } 87 | } 88 | } 89 | 90 | // minHeapUp : takes the last element and moves it up until 91 | // the Min Heap properties are satisfied 92 | func (h *MinHeap) minHeapifyUp(index int) { 93 | for h.HasParent(index) && (h.Parent(index) > h.Items[index]) { 94 | h.Swap(h.GetParentIndex(index), index) 95 | index = h.GetParentIndex(index) 96 | } 97 | } 98 | --------------------------------------------------------------------------------