├── .gitignore ├── LICENSE ├── README.md ├── common └── helper.go ├── datastructure ├── bag.go ├── binary_heap.go ├── binary_heap_test.go ├── binary_search_tree.go ├── binary_search_tree_test.go ├── graph.go ├── graph_bfs.go ├── graph_cc.go ├── graph_dfs.go ├── graph_test.go ├── hash.go ├── hash_linear_probing.go ├── hash_separate_chaining.go ├── hash_test.go ├── iterator.go ├── iterator_test.go ├── queue.go ├── queue_test.go ├── queuelinkedlist.go ├── stack.go ├── stack_test.go ├── stackarray.go ├── stacklinkedlist.go ├── tree.go ├── tree_test.go ├── trie.go ├── trie_r_way.go └── trie_ternary.go ├── mathematic ├── arithmetic.go ├── fibonacci.go ├── mathematic_test.go └── prime.go ├── sort ├── 3way_quick.go ├── bubblesort.go ├── heap.go ├── insertion.go ├── merge.go ├── merge_bottom.go ├── quick.go ├── select.go ├── selection.go ├── shell.go ├── shuffle.go ├── sort.go └── sort_test.go └── unionfind ├── .DS_Store ├── pathcompression.go ├── pathcompression_test.go ├── quickfind.go ├── quickfinduf_test.go ├── quickunion.go ├── quickunion_test.go ├── weightedqu.go └── weightedqu_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 maxime lamure 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # algorithms 2 | 3 | An implementation in GO (golang) of the basic algorithms and data structure. 4 | 5 | ## Sorting algorithms 6 | - Selection sort 7 | - Insertion sort 8 | - Bubble sort 9 | - Merge sort 10 | - Quick sort 11 | - 3 Way Quick sort 12 | - Heap sort 13 | - Select sort 14 | - Shell sort 15 | - Shuffle 16 | 17 | ## DataStructure 18 | - Queue 19 | - Linked list 20 | - Stack 21 | - Linked list 22 | - Array 23 | - Iterator 24 | - Heap 25 | - Tree 26 | - DFS pre-order traversal (Depth First Search) 27 | - DFS in order traversal (Depth First Search) 28 | - DFS post-order traversal (Depth First Search) 29 | - BFS level order (Breadth First Search) 30 | - Binaray Search Tree (BST) 31 | - Hash 32 | - Separate chaining 33 | - Linear probing 34 | - Graph (in progress) 35 | - Depth First Search (DFS) 36 | - Breadth First Search (BFS) 37 | - Connected components 38 | - Trie 39 | - R-Way Trie 40 | - Ternary Search Trie 41 | 42 | ## Union find 43 | - QuickFind 44 | - QuickUnion 45 | - Weighted QuickUnion 46 | - Weighted QuickUnion with path compression 47 | 48 | ## Mathematic 49 | - Deletion 50 | - Multiplication 51 | - Division 52 | - Pow 53 | - Fibonacci 54 | - IsPrime 55 | -------------------------------------------------------------------------------- /common/helper.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | //https://github.com/benbjohnson/testing 4 | 5 | import ( 6 | "fmt" 7 | "path/filepath" 8 | "reflect" 9 | "runtime" 10 | "testing" 11 | ) 12 | 13 | // Test represents a set of helper functions to test 14 | type Test struct{} 15 | 16 | // Assert fails the test if the condition is false. 17 | func (t *Test) Assert(tb testing.TB, condition bool, msg string, v ...interface{}) { 18 | if !condition { 19 | _, file, line, _ := runtime.Caller(1) 20 | fmt.Printf("\033[31m%s:%d: "+msg+"\033[39m\n\n", append([]interface{}{filepath.Base(file), line}, v...)...) 21 | tb.FailNow() 22 | } 23 | } 24 | 25 | // OK fails the test if an err is not nil. 26 | func (t *Test) OK(tb testing.TB, err error) { 27 | if err != nil { 28 | _, file, line, _ := runtime.Caller(1) 29 | fmt.Printf("\033[31m%s:%d: unexpected error: %s\033[39m\n\n", filepath.Base(file), line, err.Error()) 30 | tb.FailNow() 31 | } 32 | } 33 | 34 | // Equals fails the test if exp is not equal to act. 35 | func (t *Test) Equals(tb testing.TB, exp, act interface{}) { 36 | if !reflect.DeepEqual(exp, act) { 37 | _, file, line, _ := runtime.Caller(1) 38 | fmt.Printf("\033[31m%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\033[39m\n\n", filepath.Base(file), line, exp, act) 39 | tb.FailNow() 40 | } 41 | } 42 | 43 | // Swap exchanges 2 values in an array 44 | func Swap(arr []int, i, j int) { 45 | k := arr[i] 46 | arr[i] = arr[j] 47 | arr[j] = k 48 | } 49 | -------------------------------------------------------------------------------- /datastructure/bag.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | type Bag struct { 4 | bag []int 5 | index int 6 | } 7 | 8 | func NewBag() *Bag { 9 | b := &Bag{} 10 | b.bag = make([]int, 0) 11 | return b 12 | } 13 | 14 | func (b *Bag) Add(i int) { 15 | b.bag = append(b.bag, i) 16 | b.index++ 17 | } 18 | 19 | func (b *Bag) IsEmpty(i int) bool { 20 | return b.index == 0 21 | } 22 | 23 | func (b *Bag) Size() int { 24 | return b.index 25 | } 26 | 27 | func (b *Bag) Iterate() <-chan int { 28 | ch := make(chan int) 29 | go func() { 30 | for _, val := range b.bag { 31 | ch <- val 32 | } 33 | close(ch) 34 | }() 35 | return ch 36 | } 37 | -------------------------------------------------------------------------------- /datastructure/binary_heap.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/maximelamure/algorithms/common" 7 | ) 8 | 9 | // A binary heap could be represented by an array 10 | // - Largest key is arr[1], wich is root of binary tree 11 | // - Can use array indices to move through tree 12 | // - Parent of node k is k/2 13 | // - Children of node at k are at 2k and 2k+1 14 | // Insert: log N , delMax: log N , max: 1 15 | 16 | type BinaryHeap struct { 17 | arr []int 18 | lenght int 19 | } 20 | 21 | func NewBinaryHeap(capacity int) *BinaryHeap { 22 | h := &BinaryHeap{} 23 | h.arr = make([]int, capacity+1) 24 | return h 25 | } 26 | 27 | // Add add node at the end, them swim it up 28 | // At most 1 + lgN compares 29 | func (b *BinaryHeap) Add(node int) { 30 | b.lenght++ // start at 1 31 | b.arr[b.lenght] = node 32 | b.swim_up(b.lenght) 33 | } 34 | 35 | func (b *BinaryHeap) Empty() bool { 36 | return b.lenght == 0 37 | } 38 | 39 | func (b *BinaryHeap) swim_up(k int) { 40 | for { 41 | if k > 1 && b.arr[k] > b.arr[k/2] { 42 | common.Swap(b.arr, k, k/2) 43 | k = k / 2 44 | } else { 45 | break 46 | } 47 | } 48 | } 49 | 50 | // DeleteMax exchanges root with node at end, them sink it down 51 | // At most 2lnN compares 52 | func (b *BinaryHeap) DeleteMax() { 53 | common.Swap(b.arr, 1, b.lenght) 54 | b.lenght-- 55 | b.sink_down(1) 56 | b.arr[b.lenght+1] = 0 57 | } 58 | 59 | func (b *BinaryHeap) sink_down(k int) { 60 | for { 61 | if 2*k > b.lenght { 62 | break 63 | } 64 | j := 2 * k 65 | 66 | //Select the higest child 67 | if j < b.lenght && b.arr[j] < b.arr[j+1] { 68 | j++ 69 | } 70 | if b.arr[j] > b.arr[k] { 71 | common.Swap(b.arr, k, j) 72 | k = j 73 | } else { 74 | break 75 | } 76 | } 77 | } 78 | 79 | func (b *BinaryHeap) Print() { 80 | fmt.Println(b.arr) 81 | } 82 | -------------------------------------------------------------------------------- /datastructure/binary_heap_test.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/maximelamure/algorithms/sort" 7 | ) 8 | 9 | func BinarayHeap() []int { 10 | return []int{60, 50, 40, 38, 43, 36, 22} 11 | } 12 | 13 | func TestBinaryHeap(t *testing.T) { 14 | bh := BinarayHeap() 15 | su := sort.NewShuffle() 16 | su.Sort(bh) 17 | b := NewBinaryHeap(len(bh)) 18 | for _, val := range bh { 19 | b.Add(val) 20 | } 21 | b.Print() 22 | for _ = range bh { 23 | b.DeleteMax() 24 | } 25 | b.Print() 26 | } 27 | -------------------------------------------------------------------------------- /datastructure/binary_search_tree.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | import "fmt" 4 | 5 | // A BST is a binaray tree in symmetric order 6 | // A binary tree is 7 | // - either empty 8 | // - two disjoinct binary tree (left and right) 9 | // Symmetric order: each node as a key and every node's key is: 10 | // - larger than all keys in its left subtree 11 | // - smaller than all keys in its right subtree 12 | // If N distincts Keys are inserted in random order, expected heigh of tree is 13 | // ~ 4.311 ln N 14 | 15 | type binarySearchTree struct { 16 | Root *BNode 17 | } 18 | 19 | type BNode struct { 20 | Key int 21 | Value int 22 | Left *BNode 23 | Right *BNode 24 | Count int 25 | Level int 26 | } 27 | 28 | func NewBNode(key, val, count int) *BNode { 29 | return &BNode{Key: key, Value: val, Count: count} 30 | } 31 | 32 | func (b *binarySearchTree) SizeNode(node *BNode) int { 33 | if node == nil { 34 | return 0 35 | } 36 | return node.Count 37 | } 38 | 39 | func (b *binarySearchTree) Get(key int) int { 40 | 41 | x := b.Root 42 | for { 43 | if x == nil { 44 | return -1 //FIXME 45 | } 46 | 47 | if x.Key == key { 48 | return x.Value 49 | } else if x.Key > key { 50 | x = x.Left 51 | } else { 52 | x = x.Right 53 | } 54 | } 55 | } 56 | 57 | // Number of compares is equal 1 + depth of node. 58 | // If N distinct keys are inserted into a BST in random order, the expceted 59 | // number of compares for a search/insert is ~ 2 ln N (1-1 correspondence with 60 | // quick sort paritioning) 61 | 62 | func (b *binarySearchTree) Put(key, val int) { 63 | b.Root = b.put(b.Root, key, val) 64 | } 65 | 66 | func (b *binarySearchTree) put(root *BNode, key, val int) *BNode { 67 | if root == nil { 68 | return NewBNode(key, val, 1) 69 | } 70 | if key > root.Key { 71 | root.Right = b.put(root.Right, key, val) 72 | } else if key < root.Key { 73 | root.Left = b.put(root.Left, key, val) 74 | } else { 75 | root.Value = val 76 | } 77 | root.Count = 1 + b.SizeNode(root.Left) + b.SizeNode(root.Right) 78 | return root 79 | } 80 | 81 | func (b *binarySearchTree) Min() int { 82 | min := b.min(b.Root) 83 | if min != nil { 84 | return min.Value 85 | } 86 | return 0 //FIXME 87 | } 88 | func (b *binarySearchTree) min(node *BNode) *BNode { 89 | if node == nil { 90 | return nil 91 | } 92 | 93 | for { 94 | if node.Left != nil { 95 | node = node.Left 96 | } else { 97 | break 98 | } 99 | } 100 | return node 101 | } 102 | 103 | func (b *binarySearchTree) Max() int { 104 | if b.Root == nil { 105 | return -1 // FIXME: manage error 106 | } 107 | 108 | node := b.Root 109 | for { 110 | if node.Right == nil { 111 | break 112 | } 113 | node = node.Right 114 | } 115 | 116 | return node.Value 117 | } 118 | 119 | // Floor returns the largest key <= to a given key 120 | func (b *binarySearchTree) Floor(key int) int { 121 | node := b.floor(b.Root, key) 122 | if node == nil { 123 | return -1 // FIXME: manage error 124 | } 125 | return node.Key 126 | } 127 | 128 | func (b *binarySearchTree) floor(node *BNode, key int) *BNode { 129 | if node == nil || node.Key == key { 130 | return node 131 | } 132 | 133 | if key < node.Key { 134 | return b.floor(node.Left, key) 135 | } else { 136 | if t := node.Right; t != nil { 137 | return t 138 | } 139 | return node 140 | } 141 | } 142 | 143 | func (b *binarySearchTree) Size() int { 144 | return b.SizeNode(b.Root) 145 | } 146 | 147 | // Rank returns the number of key < k 148 | func (b *binarySearchTree) Rank(key int) int { 149 | return b.rank(b.Root, key) 150 | } 151 | 152 | func (b *binarySearchTree) rank(node *BNode, key int) int { 153 | if node == nil { 154 | return 0 155 | } 156 | 157 | if key == node.Key { 158 | return b.SizeNode(node.Left) 159 | } else if key < node.Key { 160 | return b.rank(node.Left, key) 161 | } else { 162 | return 1 + b.SizeNode(node.Left) + b.rank(node.Right, key) 163 | } 164 | } 165 | 166 | //In order traversal 167 | func (b *binarySearchTree) InOrder() <-chan int { 168 | q := NewQueueLinkedList() 169 | b.inOrder(b.Root, q) 170 | ch := make(chan int) 171 | go func() { 172 | for { 173 | if q.IsEmpty() { 174 | break 175 | } 176 | ch <- q.Dequeue().(int) 177 | } 178 | 179 | close(ch) 180 | 181 | }() 182 | return ch 183 | } 184 | 185 | func (b *binarySearchTree) inOrder(node *BNode, q Queue) { 186 | if node != nil { 187 | b.inOrder(node.Left, q) 188 | q.Enqueue(node.Value) 189 | b.inOrder(node.Right, q) 190 | } 191 | } 192 | 193 | func (b *binarySearchTree) DeleteMin() { 194 | b.Root = b.deleteMin(b.Root) 195 | } 196 | 197 | func (b *binarySearchTree) deleteMin(node *BNode) *BNode { 198 | if node == nil { 199 | return nil 200 | } 201 | if node.Left == nil { 202 | return node.Right 203 | } 204 | node.Left = b.deleteMin(node.Left) 205 | node.Count = 1 + b.SizeNode(node.Left) + b.SizeNode(node.Right) 206 | return node 207 | } 208 | 209 | func (b *binarySearchTree) HibbardDeletion(key int) { 210 | b.Root = b.hibbardDeletion(b.Root, key) 211 | } 212 | 213 | func (b *binarySearchTree) hibbardDeletion(node *BNode, key int) *BNode { 214 | if node == nil { 215 | return nil 216 | } 217 | 218 | //BST to find the key 219 | if key < node.Key { 220 | node.Left = b.hibbardDeletion(node.Left, key) 221 | } else if key > node.Key { 222 | node.Right = b.hibbardDeletion(node.Right, key) 223 | } else { // equality 224 | if node.Left == nil { 225 | return node.Right 226 | } 227 | if node.Right == nil { 228 | return node.Left 229 | } 230 | 231 | t := node 232 | node = b.min(t.Right) 233 | node.Right = b.deleteMin(t.Right) 234 | node.Left = t.Left 235 | } 236 | node.Count = 1 + b.SizeNode(node.Left) + b.SizeNode(node.Right) 237 | return node 238 | } 239 | 240 | func (b *binarySearchTree) String() { 241 | for x := range b.InOrder() { 242 | fmt.Print(x) 243 | } 244 | fmt.Println("") 245 | } 246 | -------------------------------------------------------------------------------- /datastructure/binary_search_tree_test.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | import ( 4 | "strconv" 5 | "testing" 6 | 7 | "github.com/maximelamure/algorithms/common" 8 | ) 9 | 10 | func TestBST(t *testing.T) { 11 | helper := common.Test{} 12 | bst := &binarySearchTree{} 13 | 14 | bst.Put(50, 50) 15 | bst.Put(25, 25) 16 | bst.Put(75, 75) 17 | bst.Put(60, 60) 18 | bst.Put(90, 90) 19 | bst.Put(10, 10) 20 | bst.Put(30, 30) 21 | bst.String() 22 | g := bst.Get(30) 23 | helper.Assert(t, g == 30, "The value should be 30. Here: "+strconv.Itoa(g)) 24 | min := bst.Min() 25 | helper.Assert(t, min == 10, "The value should be 10. Here: "+strconv.Itoa(min)) 26 | max := bst.Max() 27 | helper.Assert(t, max == 90, "The value should be 90. Here: "+strconv.Itoa(max)) 28 | floor := bst.Floor(35) 29 | helper.Assert(t, floor == 30, "The value should be 30. Here: "+strconv.Itoa(floor)) 30 | } 31 | -------------------------------------------------------------------------------- /datastructure/graph.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | ) 7 | 8 | type Graph struct { 9 | Adjacencies map[int]*Bag 10 | } 11 | 12 | // New Graph creates an empty Graph with v vertices 13 | func NewGraph() *Graph { 14 | g := &Graph{} 15 | g.Adjacencies = make(map[int]*Bag) 16 | return g 17 | 18 | } 19 | 20 | //AddEdge add an edge v-w 21 | func (g *Graph) AddEdge(v, w int) { 22 | if _, ok := g.Adjacencies[v]; !ok { 23 | g.Adjacencies[v] = NewBag() 24 | } 25 | g.Adjacencies[v].Add(w) 26 | 27 | if _, ok := g.Adjacencies[w]; !ok { 28 | g.Adjacencies[w] = NewBag() 29 | } 30 | g.Adjacencies[w].Add(v) 31 | } 32 | 33 | // Adj returns vertices adjacent to v 34 | func (g *Graph) Adj(v int) <-chan int { 35 | ch := make(chan int) 36 | go func() { 37 | if adj, ok := g.Adjacencies[v]; ok { 38 | for val := range adj.Iterate() { 39 | ch <- val 40 | } 41 | } 42 | close(ch) 43 | }() 44 | return ch 45 | } 46 | 47 | // NbVertices returns the nunber of vertices 48 | func (g *Graph) NbVertices() int { 49 | return len(g.Adjacencies) 50 | } 51 | 52 | // NbEdges returns the number of edges 53 | func (g *Graph) NbEdges() int { 54 | total := 0 55 | for _, b := range g.Adjacencies { 56 | total += b.Size() 57 | } 58 | return total / 2 59 | } 60 | 61 | // String returns the string representation of the Graph 62 | func (g *Graph) String() string { 63 | var buffer bytes.Buffer 64 | for v, b := range g.Adjacencies { 65 | for w := range b.Iterate() { 66 | buffer.WriteString(fmt.Sprintf("%s - %s", v, w)) 67 | } 68 | } 69 | return buffer.String() 70 | } 71 | 72 | // Degree computes the degree 73 | func (g *Graph) Degree(v int) int { 74 | if v, ok := g.Adjacencies[v]; ok { 75 | return v.Size() 76 | } 77 | return 0 //FIXME manage error 78 | } 79 | 80 | // MaxDegree computes the max degree 81 | func (g *Graph) MaxDegree() int { 82 | max := 0 83 | for v, _ := range g.Adjacencies { 84 | currentDegree := g.Degree(v) 85 | if currentDegree > max { 86 | max = currentDegree 87 | } 88 | } 89 | return max 90 | } 91 | 92 | // NumberOfSelfLoops returns the number of Self loops 93 | func (g *Graph) NumberOfSelfLoops() int { 94 | loop := 0 95 | for v, b := range g.Adjacencies { 96 | for w := range b.Iterate() { 97 | if w == v { 98 | loop++ 99 | } 100 | } 101 | } 102 | return loop / 2 103 | } 104 | -------------------------------------------------------------------------------- /datastructure/graph_bfs.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | // BFS computes shortest paths (fewest number of edges) from s to all other 4 | // vertices in a graph in time proportional to E+V 5 | 6 | type BFSPath struct { 7 | Source int 8 | DistTo map[int]int 9 | EdgeTo map[int]int 10 | Path Queue 11 | G *Graph 12 | } 13 | 14 | func NewBFSPath(g *Graph, source int) *BFSPath { 15 | bfsPath := &BFSPath{ 16 | DistTo: make(map[int]int), 17 | EdgeTo: make(map[int]int), 18 | G: g, 19 | Path: NewQueueLinkedList(), 20 | Source: source, 21 | } 22 | bfsPath.bfs(source) 23 | return bfsPath 24 | } 25 | 26 | func (b *BFSPath) bfs(v int) { 27 | queue := NewQueueLinkedList() 28 | b.DistTo[v] = 0 29 | queue.Enqueue(v) 30 | for { 31 | if queue.IsEmpty() { 32 | break 33 | } 34 | d := queue.Dequeue().(int) 35 | b.Path.Enqueue(d) 36 | for r := range b.G.Adj(d) { 37 | if _, ok := b.DistTo[r]; !ok { 38 | queue.Enqueue(r) 39 | b.EdgeTo[r] = d 40 | b.DistTo[r] = 1 + b.DistTo[d] 41 | } 42 | } 43 | } 44 | } 45 | 46 | func (b *BFSPath) HasPathTo(v int) bool { 47 | _, ok := b.DistTo[v] 48 | return ok 49 | } 50 | 51 | // PathTo return a the shortest path between the vertice and the source. 52 | func (b *BFSPath) PathTo(v int) <-chan interface{} { 53 | stack := NewStackArray() 54 | if b.HasPathTo(v) { 55 | for x := v; x != b.Source; x = b.EdgeTo[x] { 56 | stack.Push(x) 57 | } 58 | stack.Push(b.Source) 59 | } 60 | return stack.Iterate() 61 | } 62 | 63 | func (b *BFSPath) BFS() <-chan interface{} { 64 | return b.Path.Iterate() 65 | } 66 | -------------------------------------------------------------------------------- /datastructure/graph_cc.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | import "fmt" 4 | 5 | // Vertices v and w are connected if there is a path between them. 6 | // Preprocess the Graph to answer queries of the form is v connected to w in 7 | // constant time. 8 | 9 | // A connected component is a maximal set of connected vertices. 10 | type ConnectedComponent struct { 11 | graph *Graph 12 | cc map[int]int 13 | count int // number of connected component in the graph 14 | 15 | } 16 | 17 | // NewConnectedComponent preprocess the graph to find connected components in G 18 | func NewConnectedComponent(g *Graph) *ConnectedComponent { 19 | cc := &ConnectedComponent{ 20 | graph: g, 21 | cc: make(map[int]int), 22 | } 23 | cc.connect() 24 | return cc 25 | } 26 | 27 | func (c *ConnectedComponent) connect() { 28 | for v := range c.graph.Adjacencies { 29 | if _, ok := c.cc[v]; !ok { 30 | c.dfs(v) 31 | c.count++ 32 | } 33 | } 34 | } 35 | 36 | func (c *ConnectedComponent) dfs(v int) { 37 | c.cc[v] = c.count 38 | for w := range c.graph.Adj(v) { 39 | if _, ok := c.cc[w]; !ok { 40 | c.dfs(w) 41 | } 42 | } 43 | } 44 | 45 | // Connected returns if v an w are connected. 46 | func (c *ConnectedComponent) Connected(v, w int) bool { 47 | cv, okv := c.cc[v] 48 | if !okv { 49 | return false 50 | } 51 | cw, okw := c.cc[w] 52 | if !okw { 53 | return false 54 | } 55 | return cw == cv 56 | } 57 | 58 | // Count returns the number of connected components 59 | func (c *ConnectedComponent) Count() int { 60 | return c.count 61 | } 62 | 63 | // getID returns the componenent identifier for v 64 | func (c *ConnectedComponent) GetID(v int) int { 65 | if v, ok := c.cc[v]; ok { 66 | return v 67 | } 68 | return -1 //FIXME 69 | } 70 | 71 | func (c *ConnectedComponent) Display() { 72 | for key, val := range c.cc { 73 | fmt.Println(key, " - ", val) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /datastructure/graph_dfs.go: -------------------------------------------------------------------------------- 1 | // In progress 2 | package datastructure 3 | 4 | import "fmt" 5 | 6 | type DFSPath struct { 7 | Source int 8 | Marked map[int]bool 9 | Adj map[int]int 10 | G *Graph 11 | } 12 | 13 | func NewDFSPath(g *Graph, source int) *DFSPath { 14 | dfspath := &DFSPath{ 15 | Marked: make(map[int]bool), 16 | Adj: make(map[int]int), 17 | G: g, 18 | Source: source, 19 | } 20 | dfspath.dfs(source) 21 | return dfspath 22 | } 23 | 24 | func (g *DFSPath) dfs(v int) { 25 | g.Marked[v] = true 26 | for w := range g.G.Adj(v) { 27 | if !g.Marked[w] { 28 | g.dfs(w) 29 | g.Adj[w] = v 30 | } 31 | } 32 | } 33 | 34 | func (g *DFSPath) Print() { 35 | fmt.Println("Marked") 36 | for k, _ := range g.Marked { 37 | fmt.Println(k) 38 | } 39 | fmt.Println("ADJ") 40 | for k, v := range g.Adj { 41 | fmt.Println(k, "-", v) 42 | } 43 | } 44 | 45 | func (g *DFSPath) HasPathTo(v int) bool { 46 | return g.Marked[v] 47 | } 48 | 49 | // PathTo return a path between the vertice and the source 50 | func (g *DFSPath) PathTo(v int) <-chan interface{} { 51 | stack := NewStackArray() 52 | if g.HasPathTo(v) { 53 | 54 | for x := v; x != g.Source; x = g.Adj[x] { 55 | stack.Push(x) 56 | } 57 | stack.Push(g.Source) 58 | } 59 | return stack.Iterate() 60 | } 61 | -------------------------------------------------------------------------------- /datastructure/graph_test.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "strconv" 7 | "testing" 8 | 9 | "github.com/maximelamure/api/common" 10 | ) 11 | 12 | func GetGraph() *Graph { 13 | g := NewGraph() 14 | g.AddEdge(0, 1) 15 | g.AddEdge(0, 2) 16 | g.AddEdge(0, 6) 17 | g.AddEdge(0, 5) 18 | g.AddEdge(5, 3) 19 | g.AddEdge(3, 4) 20 | g.AddEdge(4, 6) 21 | g.AddEdge(7, 8) 22 | g.AddEdge(9, 10) 23 | g.AddEdge(9, 12) 24 | g.AddEdge(9, 11) 25 | g.AddEdge(11, 12) 26 | g.AddEdge(11, 11) 27 | return g 28 | } 29 | 30 | func TestGraph(t *testing.T) { 31 | g := GetGraph() 32 | helper := common.Test{} 33 | nb := 0 34 | for _ = range g.Adj(0) { 35 | nb++ 36 | } 37 | helper.Assert(t, nb == 4, "The number of adjecent vertices should be 4") 38 | 39 | //nb vertices 40 | helper.Assert(t, g.NbVertices() == 13, "The number of vertices should be 13") 41 | 42 | //nb edges 43 | helper.Assert(t, g.NbEdges() == 13, "The number of edges should be 13, get "+strconv.Itoa(g.NbEdges())) 44 | 45 | //degree 46 | helper.Assert(t, g.Degree(0) == 4, "The degree of the vertice 0 should be 4") 47 | 48 | //max degree 49 | helper.Assert(t, g.MaxDegree() == 4, "The max degree of the graph should be 4") 50 | 51 | //nb self loop 52 | helper.Assert(t, g.NumberOfSelfLoops() == 1, "The number of loop should be 1, get "+strconv.Itoa(g.NumberOfSelfLoops())) 53 | } 54 | 55 | func TestDFS(t *testing.T) { 56 | helper := common.Test{} 57 | g := GetGraph() 58 | dfs := NewDFSPath(g, 0) 59 | nbVertices := 0 60 | log.Println("Path To 5") 61 | for x := range dfs.PathTo(5) { 62 | log.Println(x) 63 | nbVertices++ 64 | } 65 | helper.Assert(t, nbVertices == 5, "The number of vertices should be 5, get:"+strconv.Itoa(nbVertices)) 66 | 67 | nbVertices = 0 68 | log.Println("Path To 11") 69 | for x := range dfs.PathTo(11) { 70 | log.Println(x) 71 | nbVertices++ 72 | } 73 | helper.Assert(t, nbVertices == 0, "The number of vertices should be 0, get:"+strconv.Itoa(nbVertices)) 74 | } 75 | 76 | func TestBFS(t *testing.T) { 77 | helper := common.Test{} 78 | g := GetGraph() 79 | bfs := NewBFSPath(g, 0) 80 | 81 | nbVertices := 0 82 | for _ = range bfs.PathTo(3) { 83 | nbVertices++ 84 | } 85 | helper.Assert(t, nbVertices == 3, "The number of vertices should be 3, get:"+strconv.Itoa(nbVertices)) 86 | 87 | for x := range bfs.BFS() { 88 | fmt.Println(x) 89 | } 90 | } 91 | 92 | func TestCC(t *testing.T) { 93 | helper := common.Test{} 94 | g := GetGraph() 95 | bfs := NewConnectedComponent(g) 96 | bfs.Display() 97 | helper.Assert(t, bfs.GetID(5) == bfs.GetID(6), "5 and 6 should be connected") 98 | helper.Assert(t, bfs.GetID(9) == bfs.GetID(12), "9 and 12 should be connected") 99 | helper.Assert(t, bfs.GetID(5) != bfs.GetID(11), "5 and 11 should not be connected") 100 | } 101 | -------------------------------------------------------------------------------- /datastructure/hash.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | type Hash interface { 4 | Get(key string) string 5 | Put(key, value string) 6 | } 7 | -------------------------------------------------------------------------------- /datastructure/hash_linear_probing.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | import "hash/fnv" 4 | 5 | // Under uniform hashing assumption, the average # of probes in a linear 6 | // probing hash table of size M that contains N = alpha M keys 7 | // - M too large => too many empty array entries 8 | // - M too small => search time blow up 9 | // - Typical choice alpha ~ N / M ~ 1/2 10 | // Worst case : ln N, Average case : constant (3-5) 11 | 12 | type hashLinearProbing struct { 13 | m int 14 | Keys []interface{} 15 | Values []interface{} 16 | } 17 | 18 | func NewHashLinearProbing() Hash { 19 | h := &hashLinearProbing{} 20 | h.m = 30001 21 | h.Keys = make([]interface{}, h.m) 22 | h.Values = make([]interface{}, h.m) 23 | return h 24 | } 25 | 26 | func (h *hashLinearProbing) hash(key string) int { 27 | ha := fnv.New32a() 28 | ha.Write([]byte(key)) 29 | return int(ha.Sum32()&0x7fffffff) % h.m 30 | } 31 | 32 | func (h *hashLinearProbing) Get(key string) string { 33 | i := h.hash(key) 34 | for ; h.Keys[i] != nil; i = (i + 1) % h.m { 35 | if h.Keys[i] == key { 36 | return h.Values[i].(string) 37 | } 38 | } 39 | return "" 40 | } 41 | 42 | func (h *hashLinearProbing) Put(key, value string) { 43 | i := h.hash(key) 44 | for ; h.Keys[i] != nil; i = (i + 1) % h.m { 45 | if h.Keys[i] == key { 46 | h.Values[i] = value 47 | break 48 | } 49 | } 50 | h.Keys[i] = key 51 | h.Values[i] = value 52 | 53 | } 54 | -------------------------------------------------------------------------------- /datastructure/hash_separate_chaining.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | import "hash/fnv" 4 | 5 | // Under uniform hashing assumption, prob. that the number of key in a list is 6 | // within a constant factor of N/M is extremely close to 1. 7 | // Number of probes for search/insert is proportional to N/M 8 | // - M too large => too many empty chains 9 | // - M too small => chains too long 10 | // - Typical choice: M ~ N/5 constant times ops 11 | // Worst case : ln N, Average case : constant (3-5) 12 | 13 | type hashSeperateChaining struct { 14 | m int 15 | st []*HNode 16 | } 17 | 18 | type HNode struct { 19 | Key string 20 | Value string 21 | Next *HNode 22 | } 23 | 24 | func NewHashSeperateChaining() Hash { 25 | ht := &hashSeperateChaining{} 26 | ht.m = 97 27 | ht.st = make([]*HNode, ht.m) 28 | return ht 29 | } 30 | 31 | func (h *hashSeperateChaining) Get(key string) string { 32 | hash := h.hash(key) 33 | 34 | for x := h.st[hash]; x != nil; x = x.Next { 35 | if x.Key == key { 36 | return x.Value 37 | } 38 | } 39 | return "" 40 | } 41 | 42 | func (h *hashSeperateChaining) hash(key string) int { 43 | ha := fnv.New32a() 44 | ha.Write([]byte(key)) 45 | return int(ha.Sum32()&0x7fffffff) % h.m 46 | } 47 | 48 | func (h *hashSeperateChaining) Put(key, value string) { 49 | hash := h.hash(key) 50 | 51 | for x := h.st[hash]; x != nil; x = x.Next { 52 | if x.Key == key { 53 | x.Value = value 54 | return 55 | } 56 | } 57 | 58 | n := &HNode{} 59 | n.Value = value 60 | n.Key = key 61 | n.Next = h.st[hash] 62 | h.st[hash] = n 63 | } 64 | -------------------------------------------------------------------------------- /datastructure/hash_test.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/maximelamure/api/common" 7 | ) 8 | 9 | func TestHashLinear(t *testing.T) { 10 | h := NewHashLinearProbing() 11 | testHash(h, t) 12 | } 13 | 14 | func TestHashSeparate(t *testing.T) { 15 | h := NewHashSeperateChaining() 16 | testHash(h, t) 17 | } 18 | 19 | func testHash(h Hash, t *testing.T) { 20 | helper := common.Test{} 21 | 22 | h.Put("maxime", "lamure") 23 | h.Put("florie", "perouze") 24 | 25 | v1 := h.Get("maxime") 26 | helper.Assert(t, v1 == "lamure", "The value should be lamure. Here: "+v1) 27 | h.Put("florie", "lamure") 28 | v1 = h.Get("florie") 29 | helper.Assert(t, v1 == "lamure", "The value should be lamure. Here: "+v1) 30 | } 31 | -------------------------------------------------------------------------------- /datastructure/iterator.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | //SimpleIterator is a simple struct to illustrate an implementation of an iterator 4 | type SimpleIterator struct { 5 | fullNames []string 6 | Length int 7 | } 8 | 9 | // NewSimpleIterator initialize a new SimpleIterator 10 | func NewSimpleIterator() *SimpleIterator { 11 | si := &SimpleIterator{} 12 | si.fullNames = []string{"Maxime", "Florie", "Louise", "Victoire"} 13 | si.Length = 4 14 | return si 15 | } 16 | 17 | // Names return an Iterator by using a chanel 18 | func (s *SimpleIterator) Names() <-chan string { 19 | ch := make(chan string) 20 | go func() { 21 | for _, v := range s.fullNames { 22 | ch <- v 23 | } 24 | close(ch) 25 | }() 26 | return ch 27 | } 28 | -------------------------------------------------------------------------------- /datastructure/iterator_test.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "testing" 7 | 8 | "github.com/maximelamure/api/common" 9 | ) 10 | 11 | func TestIterator(t *testing.T) { 12 | helper := common.Test{} 13 | i := NewSimpleIterator() 14 | counter := 0 15 | 16 | for item := range i.Names() { 17 | fmt.Println(item) 18 | counter++ 19 | } 20 | 21 | helper.Assert(t, counter == i.Length, "The number of iteration should be "+strconv.Itoa(i.Length)+" . Here: "+strconv.Itoa(counter)) 22 | } 23 | -------------------------------------------------------------------------------- /datastructure/queue.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | type Queue interface { 4 | Enqueue(obj interface{}) 5 | Dequeue() interface{} 6 | IsEmpty() bool 7 | Size() int 8 | Iterate() <-chan interface{} 9 | } 10 | -------------------------------------------------------------------------------- /datastructure/queue_test.go: -------------------------------------------------------------------------------- 1 | package datastructure_test 2 | 3 | import ( 4 | "strconv" 5 | "testing" 6 | 7 | "github.com/maximelamure/algorithms/common" 8 | "github.com/maximelamure/algorithms/datastructure" 9 | ) 10 | 11 | func TestQueueLinkedList(t *testing.T) { 12 | queue := datastructure.NewQueueLinkedList() 13 | testQueue(queue, t) 14 | } 15 | 16 | func testQueue(queue datastructure.Queue, t *testing.T) { 17 | helper := common.Test{} 18 | queue.Enqueue(1) 19 | queue.Enqueue(2) 20 | queue.Enqueue(3) 21 | 22 | helper.Assert(t, !queue.IsEmpty(), "The queue should not be empty") 23 | helper.Assert(t, queue.Size() == 3, "The queue length should be 3") 24 | queue.Dequeue() 25 | queue.Dequeue() 26 | item := queue.Dequeue() 27 | helper.Assert(t, item.(int) == 3, "The value should be 3. Here: "+strconv.Itoa(item.(int))) 28 | } 29 | -------------------------------------------------------------------------------- /datastructure/queuelinkedlist.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | type queueLinkedList struct { 4 | First *Node 5 | Last *Node 6 | Length int 7 | } 8 | 9 | type Node struct { 10 | Next *Node 11 | Value interface{} 12 | } 13 | 14 | func NewQueueLinkedList() Queue { 15 | return &queueLinkedList{} 16 | } 17 | 18 | func (q *queueLinkedList) Enqueue(value interface{}) { 19 | oldLast := q.Last 20 | q.Last = &Node{} 21 | q.Last.Value = value 22 | 23 | if q.IsEmpty() { 24 | q.First = q.Last 25 | } else { 26 | oldLast.Next = q.Last 27 | } 28 | 29 | q.Length++ 30 | } 31 | 32 | func (q *queueLinkedList) Dequeue() interface{} { 33 | if !q.IsEmpty() { 34 | item := q.First.Value 35 | q.Length-- 36 | q.First = q.First.Next 37 | if q.Length == 0 { 38 | q.Last = q.First 39 | } 40 | return item 41 | } 42 | 43 | return 0 //FIXME 44 | } 45 | func (q *queueLinkedList) IsEmpty() bool { 46 | return q.Size() == 0 47 | } 48 | func (q *queueLinkedList) Size() int { 49 | return q.Length 50 | } 51 | 52 | func (q *queueLinkedList) Iterate() <-chan interface{} { 53 | ch := make(chan interface{}) 54 | go func() { 55 | for { 56 | if q.IsEmpty() { 57 | break 58 | } 59 | ch <- q.Dequeue() 60 | } 61 | close(ch) 62 | }() 63 | return ch 64 | } 65 | -------------------------------------------------------------------------------- /datastructure/stack.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | type Stack interface { 4 | Push(item interface{}) 5 | Pop() interface{} 6 | IsEmpty() bool 7 | Size() int 8 | Iterate() <-chan interface{} 9 | } 10 | -------------------------------------------------------------------------------- /datastructure/stack_test.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | import ( 4 | "strconv" 5 | "testing" 6 | 7 | "github.com/maximelamure/api/common" 8 | ) 9 | 10 | func TestStackArray(t *testing.T) { 11 | stack := NewStackArray() 12 | testStack(stack, t) 13 | } 14 | 15 | func TestLinkedList(t *testing.T) { 16 | stack := NewStackLinkedList() 17 | testStack(stack, t) 18 | } 19 | 20 | func testStack(stack Stack, t *testing.T) { 21 | helper := common.Test{} 22 | stack.Push(1) 23 | stack.Push(2) 24 | stack.Push(3) 25 | helper.Assert(t, !stack.IsEmpty(), "The stack should not be empty") 26 | helper.Assert(t, stack.Size() == 3, "The stack length should be 3") 27 | pop := stack.Pop() 28 | stack.Push(4) 29 | pop = stack.Pop() 30 | helper.Assert(t, pop.(int) == 4, "The value should be 4. Here: "+strconv.Itoa(pop.(int))) 31 | pop = stack.Pop() 32 | helper.Assert(t, pop.(int) == 2, "The value should be 2 Here: "+strconv.Itoa(pop.(int))) 33 | 34 | } 35 | -------------------------------------------------------------------------------- /datastructure/stackarray.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | type stackArray struct { 4 | Items []interface{} 5 | Index int 6 | } 7 | 8 | func NewStackArray() Stack { 9 | obj := &stackArray{} 10 | obj.Items = make([]interface{}, 0) 11 | return obj 12 | } 13 | 14 | func (s *stackArray) Push(item interface{}) { 15 | s.Resize() 16 | s.Items[s.Index] = item 17 | s.Index++ 18 | } 19 | 20 | func (s *stackArray) Pop() interface{} { 21 | if !s.IsEmpty() { 22 | item := s.Items[s.Index-1] 23 | s.Index-- 24 | s.Resize() 25 | return item 26 | } 27 | 28 | return 0 //FIXME 29 | } 30 | 31 | func (s *stackArray) Resize() { 32 | if cap(s.Items)/4 > s.Index { 33 | s.Items = s.Items[0 : cap(s.Items)/2] 34 | } else if cap(s.Items) == s.Index { 35 | c := make([]interface{}, 1+s.Index*2) 36 | copy(c, s.Items) 37 | s.Items = c 38 | } 39 | } 40 | 41 | func (s *stackArray) IsEmpty() bool { 42 | return s.Size() == 0 43 | } 44 | 45 | func (s *stackArray) Size() int { 46 | return s.Index 47 | } 48 | 49 | func (s *stackArray) Iterate() <-chan interface{} { 50 | ch := make(chan interface{}) 51 | go func() { 52 | for { 53 | if s.IsEmpty() { 54 | break 55 | } 56 | ch <- s.Pop() 57 | } 58 | close(ch) 59 | 60 | }() 61 | return ch 62 | } 63 | -------------------------------------------------------------------------------- /datastructure/stacklinkedlist.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | type stackLinkedList struct { 4 | Current *node 5 | Lenght int 6 | } 7 | 8 | type node struct { 9 | Item interface{} 10 | Next *node 11 | } 12 | 13 | func NewStackLinkedList() Stack { 14 | return &stackLinkedList{} 15 | } 16 | 17 | func (s *stackLinkedList) Push(obj interface{}) { 18 | newNode := &node{} 19 | newNode.Item = obj 20 | newNode.Next = s.Current 21 | s.Current = newNode 22 | s.Lenght++ 23 | } 24 | 25 | func (s *stackLinkedList) Pop() interface{} { 26 | if !s.IsEmpty() { 27 | item := s.Current.Item 28 | s.Current = s.Current.Next 29 | s.Lenght-- 30 | return item 31 | } 32 | return 0 //FIXME 33 | } 34 | 35 | func (s *stackLinkedList) IsEmpty() bool { 36 | return s.Lenght == 0 37 | } 38 | 39 | func (s *stackLinkedList) Size() int { 40 | return s.Lenght 41 | } 42 | 43 | func (s *stackLinkedList) Iterate() <-chan interface{} { 44 | ch := make(chan interface{}) 45 | go func() { 46 | for { 47 | if s.IsEmpty() { 48 | break 49 | } 50 | ch <- s.Pop() 51 | } 52 | close(ch) 53 | 54 | }() 55 | return ch 56 | } 57 | -------------------------------------------------------------------------------- /datastructure/tree.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | import "fmt" 4 | 5 | // A Tree is a simple binaray tree 6 | type Tree struct { 7 | root *TNode 8 | } 9 | 10 | type TNode struct { 11 | key int 12 | value int 13 | left *TNode 14 | right *TNode 15 | level int 16 | } 17 | 18 | // BFS traverses the tree in the level order 19 | func (t *Tree) BFS() <-chan int { 20 | ch := make(chan int) 21 | go func() { 22 | if t.root != nil { 23 | queue := NewQueueLinkedList() 24 | queue.Enqueue(t.root) 25 | for { 26 | if queue.IsEmpty() { 27 | break 28 | } 29 | n := queue.Dequeue().(*TNode) 30 | ch <- n.value 31 | if n.left != nil { 32 | queue.Enqueue(n.left) 33 | } 34 | if n.right != nil { 35 | queue.Enqueue(n.right) 36 | } 37 | } 38 | } 39 | close(ch) 40 | }() 41 | 42 | return ch 43 | } 44 | 45 | // DFS traverse the tree in pre-order 46 | func (t *Tree) DFS() <-chan int { 47 | ch := make(chan int) 48 | go func() { 49 | if t.root != nil { 50 | stack := NewStackArray() 51 | stack.Push(t.root) 52 | for { 53 | if stack.IsEmpty() { 54 | break 55 | } 56 | n := stack.Pop().(*TNode) 57 | ch <- n.value 58 | if n.right != nil { 59 | stack.Push(n.right) 60 | } 61 | if n.left != nil { 62 | stack.Push(n.left) 63 | } 64 | } 65 | } 66 | close(ch) 67 | }() 68 | return ch 69 | } 70 | 71 | // InOrder traverse the tree in in-order 72 | func (t *Tree) InOrder() <-chan int { 73 | ch := make(chan int) 74 | go func() { 75 | t.inOrder(t.root, ch) 76 | close(ch) 77 | }() 78 | return ch 79 | } 80 | 81 | func (t *Tree) inOrder(node *TNode, ch chan int) { 82 | if node != nil { 83 | t.inOrder(node.left, ch) 84 | ch <- node.value 85 | t.inOrder(node.right, ch) 86 | } 87 | } 88 | 89 | // PostOrder traverse the tree in post-order 90 | func (t *Tree) PostOrder() <-chan int { 91 | ch := make(chan int) 92 | go func() { 93 | t.postOrder(t.root, ch) 94 | close(ch) 95 | }() 96 | return ch 97 | } 98 | 99 | func (t *Tree) postOrder(node *TNode, ch chan int) { 100 | if node != nil { 101 | t.postOrder(node.left, ch) 102 | t.postOrder(node.right, ch) 103 | ch <- node.value 104 | } 105 | } 106 | 107 | func (t *Tree) DisplayBFS() { 108 | if t.root == nil { 109 | return 110 | } 111 | queue := NewQueueLinkedList() 112 | currentLevel := 0 113 | nbItemByLevel := 0 114 | queue.Enqueue(t.root) 115 | for { 116 | if queue.IsEmpty() { 117 | return 118 | } 119 | current := queue.Dequeue().(*TNode) 120 | if currentLevel != current.level { 121 | fmt.Println("") 122 | currentLevel++ 123 | nbItemByLevel = 0 124 | } 125 | if nbItemByLevel > 0 { 126 | fmt.Print(",") 127 | } 128 | fmt.Print(current.value) 129 | nbItemByLevel++ 130 | 131 | if current.left != nil { 132 | current.left.level = current.level + 1 133 | queue.Enqueue(current.left) 134 | } 135 | if current.right != nil { 136 | current.right.level = current.level + 1 137 | queue.Enqueue(current.right) 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /datastructure/tree_test.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "strconv" 7 | "testing" 8 | 9 | "github.com/maximelamure/algorithms/common" 10 | ) 11 | 12 | func GenerateTree() (tree *Tree, bfs []int, dfs []int, inorder []int, postOrder []int) { 13 | return &Tree{ 14 | root: &TNode{ 15 | key: 5, 16 | value: 5, 17 | left: &TNode{ 18 | key: 2, 19 | value: 2, 20 | left: &TNode{ 21 | key: 0, 22 | value: 0, 23 | }, 24 | right: &TNode{ 25 | key: 1, 26 | value: 1, 27 | }, 28 | }, 29 | right: &TNode{ 30 | key: 8, 31 | value: 8, 32 | right: &TNode{ 33 | key: 3, 34 | value: 3, 35 | }, 36 | }, 37 | }, 38 | }, 39 | []int{5, 2, 8, 0, 1, 3}, 40 | []int{5, 2, 0, 1, 8, 3}, 41 | []int{0, 2, 1, 5, 8, 3}, 42 | []int{0, 1, 2, 3, 8, 5} 43 | } 44 | 45 | func TestTree(t *testing.T) { 46 | helper := common.Test{} 47 | tree, bfs, dfs, inorder, postorder := GenerateTree() 48 | i := 0 49 | for x := range tree.BFS() { 50 | helper.Assert(t, x == bfs[i], "The value should be "+strconv.Itoa(bfs[i])+" here: "+strconv.Itoa(x)) 51 | i++ 52 | } 53 | i = 0 54 | fmt.Println("DFS") 55 | for x := range tree.DFS() { 56 | log.Print(x, " ") 57 | helper.Assert(t, x == dfs[i], "The value should be "+strconv.Itoa(dfs[i])+" here: "+strconv.Itoa(x)) 58 | i++ 59 | } 60 | 61 | i = 0 62 | fmt.Println("InOrder") 63 | for x := range tree.InOrder() { 64 | log.Print(x, " ") 65 | helper.Assert(t, x == inorder[i], "The value should be "+strconv.Itoa(inorder[i])+" here: "+strconv.Itoa(x)) 66 | i++ 67 | } 68 | 69 | i = 0 70 | fmt.Println("PostOrder") 71 | for x := range tree.PostOrder() { 72 | log.Print(x, " ") 73 | helper.Assert(t, x == postorder[i], "The value should be "+strconv.Itoa(postorder[i])+" here: "+strconv.Itoa(x)) 74 | i++ 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /datastructure/trie.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | type Trie interface { 4 | Put(key string, val interface{}) 5 | Get(key string) interface{} 6 | } 7 | -------------------------------------------------------------------------------- /datastructure/trie_r_way.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | type TrieRWay struct { 4 | N int 5 | Root *TRNode 6 | } 7 | 8 | type TRNode struct { 9 | Key interface{} 10 | Next []*TRNode 11 | } 12 | 13 | func NewTrieRWay(size int) Trie { 14 | return &TrieRWay{ 15 | N: size, 16 | } 17 | } 18 | 19 | func (t *TrieRWay) Put(key string, val interface{}) { 20 | if len(key) == 0 { 21 | return 22 | } 23 | 24 | t.Root = t.put(t.Root, key, val, 0) 25 | } 26 | 27 | func (t *TrieRWay) put(node *TRNode, key string, val interface{}, position int) *TRNode { 28 | if node == nil { 29 | node = &TRNode{ 30 | Next: make([]*TRNode, t.N), 31 | } 32 | } 33 | if position == len(key)-1 { 34 | node.Key = val 35 | return node 36 | } 37 | index := key[position] - 'a' 38 | node.Next[index] = t.put(node.Next[index], key, val, position+1) 39 | return node 40 | } 41 | 42 | func (t *TrieRWay) Get(key string) interface{} { 43 | return t.get(t.Root, key, 0) 44 | } 45 | 46 | func (t *TrieRWay) get(node *TRNode, key string, position int) interface{} { 47 | if node == nil { 48 | return nil 49 | } 50 | 51 | if position == len(key)-1 { 52 | return node.Key 53 | } 54 | 55 | index := key[position] - 'a' 56 | return t.get(node.Next[index], key, position+1) 57 | } 58 | -------------------------------------------------------------------------------- /datastructure/trie_ternary.go: -------------------------------------------------------------------------------- 1 | package datastructure 2 | 3 | type Trie_Ternary struct { 4 | Root *TTNode 5 | } 6 | 7 | type TTNode struct { 8 | Key string 9 | Value interface{} 10 | Left *TTNode 11 | Right *TTNode 12 | Middle *TTNode 13 | } 14 | 15 | func NewTrieTernary() Trie { 16 | return &Trie_Ternary{} 17 | } 18 | 19 | func (t *Trie_Ternary) Put(key string, val interface{}) { 20 | t.Root = t.put(t.Root, key, val, 0) 21 | } 22 | 23 | func (t *Trie_Ternary) put(node *TTNode, key string, val interface{}, position int) *TTNode { 24 | if node == nil { 25 | node = &TTNode{ 26 | Key: string(key[position]), 27 | } 28 | } 29 | if position == len(key) { 30 | node.Value = val 31 | return node 32 | } 33 | 34 | cmp := (key[position] - 'a') - (node.Key[0] - 'a') 35 | if cmp == 0 { 36 | node.Middle = t.put(node.Middle, key, val, position+1) 37 | } else if cmp < 0 { 38 | node.Left = t.put(node.Left, key, val, position) 39 | } else { 40 | node.Right = t.put(node.Right, key, val, position) 41 | } 42 | return node 43 | } 44 | 45 | func (t *Trie_Ternary) Get(key string) interface{} { 46 | return t.get(t.Root, key, 0) 47 | } 48 | 49 | func (t *Trie_Ternary) get(node *TTNode, key string, position int) interface{} { 50 | if node == nil { 51 | return nil 52 | } 53 | if position >= len(key) { 54 | return node.Value 55 | } 56 | cmp := (key[position] - 'a') - (node.Key[0] - 'a') 57 | if cmp == 0 { 58 | return t.get(node.Middle, key, position+1) 59 | } else if cmp < 0 { 60 | return t.get(node.Left, key, position) 61 | } else { 62 | return t.get(node.Right, key, position) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /mathematic/arithmetic.go: -------------------------------------------------------------------------------- 1 | package mathematic 2 | 3 | import "errors" 4 | 5 | // SubstractAddOnly implements a substaction with only the Add operator 6 | func SubstractAddOnly(a, b int) int { 7 | return a + Min(b) 8 | } 9 | 10 | func Min(b int) int { 11 | result := 0 12 | d := -1 13 | if b < 0 { 14 | d = 1 15 | } 16 | for ; b != 0; b += d { 17 | result += d 18 | } 19 | return result 20 | } 21 | 22 | func Abs(a int) int { 23 | if a < 0 { 24 | return -a 25 | } else { 26 | return a 27 | } 28 | } 29 | 30 | // MultiplyAddOnly implements a multiplication with only the Add operator 31 | func MultiplyAddOnly(a, b int) int { 32 | if a < b { 33 | MultiplyAddOnly(b, a) 34 | } 35 | 36 | result := 0 37 | for x := 0; x < Abs(b); x++ { 38 | result += a 39 | } 40 | 41 | if b < 0 { 42 | result = Min(result) 43 | } 44 | return result 45 | } 46 | 47 | // DivideAddOnly implements a division with only the Add operator 48 | func DivideAddOnly(a, b int) (int, error) { 49 | if b == 0 { 50 | return 0, errors.New("Can't divide by 0") 51 | } 52 | 53 | result := 0 54 | for x := Abs(a); x >= Abs(b); x = SubstractAddOnly(x, Abs(b)) { 55 | result++ 56 | } 57 | if (b < 0 && a > 0) || (b > 0 && a < 0) { 58 | result = Min(result) 59 | } 60 | 61 | return result, nil 62 | } 63 | 64 | func Pow(a, b int) int { 65 | if a == 0 && b != 0 { 66 | return 0 67 | } 68 | if b == 0 { 69 | return 1 70 | } 71 | 72 | mid := Pow(a, (b-1)/2) 73 | mid *= mid 74 | if b%2 != 0 { 75 | mid *= a 76 | } 77 | 78 | return mid 79 | } 80 | 81 | func Multiply(a, b int) int { 82 | if a == 0 || b == 0 { 83 | return 0 84 | } 85 | if a < b { 86 | return Multiply(b, a) 87 | } 88 | 89 | if b == 1 { 90 | return a 91 | } 92 | if b == 2 { 93 | return a + a 94 | } 95 | temp := Multiply(a, (b-1)/2) 96 | temp += temp + a 97 | return temp 98 | 99 | } 100 | -------------------------------------------------------------------------------- /mathematic/fibonacci.go: -------------------------------------------------------------------------------- 1 | package mathematic 2 | 3 | func Fibonacci(n int) int { 4 | if n == 1 || n == 0 { 5 | return n 6 | } 7 | return Fibonacci(n-1) + Fibonacci(n-2) 8 | } 9 | 10 | func FibonacciDyamic(n int) int { 11 | arr := make([]int, n+1, n+1) 12 | arr[0] = 0 13 | arr[1] = 1 14 | for x := 2; x <= n; x++ { 15 | arr[x] = -1 16 | } 17 | return fibonacciDyamic(n, arr) 18 | } 19 | 20 | func fibonacciDyamic(n int, arr []int) int { 21 | if val := arr[n]; val != -1 { 22 | return val 23 | } 24 | arr[n-1] = fibonacciDyamic(n-1, arr) 25 | arr[n-2] = fibonacciDyamic(n-2, arr) 26 | return arr[n-1] + arr[n-2] 27 | } 28 | -------------------------------------------------------------------------------- /mathematic/mathematic_test.go: -------------------------------------------------------------------------------- 1 | package mathematic_test 2 | 3 | import ( 4 | "log" 5 | "testing" 6 | "time" 7 | 8 | "github.com/maximelamure/algorithms/mathematic" 9 | "github.com/maximelamure/api/common" 10 | ) 11 | 12 | var helper common.Test = common.Test{} 13 | 14 | func TestSub(t *testing.T) { 15 | helper.Assert(t, mathematic.SubstractAddOnly(5, 3) == 2, "Substract 5 3 should be 2") 16 | helper.Assert(t, mathematic.SubstractAddOnly(5, -3) == 8, "Substract 5 -3 should be 8") 17 | helper.Assert(t, mathematic.SubstractAddOnly(-5, -3) == -2, "Substract -5 -3 should be -2") 18 | } 19 | 20 | func TestMultiplication(t *testing.T) { 21 | helper.Assert(t, mathematic.MultiplyAddOnly(5, 3) == 15, "Multiply 5 3 should be 15") 22 | helper.Assert(t, mathematic.MultiplyAddOnly(5, -3) == -15, "Multiply 5 -3 should be -15") 23 | helper.Assert(t, mathematic.MultiplyAddOnly(-5, -3) == 15, "Multiply -5 -3 should be 15") 24 | log.Print(mathematic.Multiply(5, 1)) 25 | helper.Assert(t, mathematic.Multiply(5, 1) == 5, "Multiply 5 1 should be 5") 26 | log.Print(mathematic.Multiply(5, 2)) 27 | helper.Assert(t, mathematic.Multiply(5, 2) == 10, "Multiply 5 2 should be 10") 28 | log.Print(mathematic.Multiply(5, 3)) 29 | helper.Assert(t, mathematic.Multiply(5, 3) == 15, "Multiply 5 3 should be 15") 30 | } 31 | 32 | func TestDivision(t *testing.T) { 33 | val, _ := mathematic.DivideAddOnly(5, 3) 34 | helper.Assert(t, val == 1, "Division 5 3 should be 1") 35 | val, _ = mathematic.DivideAddOnly(-5, -3) 36 | helper.Assert(t, val == 1, "Division -5 -3 should be 1") 37 | val, _ = mathematic.DivideAddOnly(5, -3) 38 | helper.Assert(t, val == -1, "Division 5 -3 should be -1") 39 | val, _ = mathematic.DivideAddOnly(180, 5) 40 | helper.Assert(t, val == 36, "Division 180 5 should be 36") 41 | } 42 | 43 | func TestFibonacci(t *testing.T) { 44 | start := time.Now() 45 | helper.Assert(t, mathematic.Fibonacci(10) == 55, "Fibonacci 10 should be 55") 46 | log.Printf("Fibonacci tooks %v to run.\n", time.Now().Sub(start)) 47 | start = time.Now() 48 | helper.Assert(t, mathematic.FibonacciDyamic(10) == 55, "Fibonacci 10 should be 55") 49 | log.Printf("FibonacciDyamic tooks %v to run.\n", time.Now().Sub(start)) 50 | } 51 | 52 | func TestIsPrime(t *testing.T) { 53 | helper.Assert(t, !mathematic.IsPrime(358), "358 is not prime") 54 | helper.Assert(t, mathematic.IsPrime(997), "997 is Prime") 55 | } 56 | 57 | func TestPow(t *testing.T) { 58 | helper.Assert(t, mathematic.Pow(2, 3) == 8, "Pow(2,3) should be 8") 59 | helper.Assert(t, mathematic.Pow(0, 0) == 1, "Pow(0,0) should be 1") 60 | helper.Assert(t, mathematic.Pow(5, 0) == 1, "Pow(5,0) should be 1") 61 | helper.Assert(t, mathematic.Pow(0, 5) == 0, "Pow(0,5) should be 0") 62 | } 63 | -------------------------------------------------------------------------------- /mathematic/prime.go: -------------------------------------------------------------------------------- 1 | package mathematic 2 | 3 | func IsPrime(n int) bool { 4 | if n == 1 { 5 | return false 6 | } 7 | if n == 2 { 8 | return true 9 | } 10 | 11 | for x := 2; x*x <= n; x = x + 1 { 12 | if n%x == 0 { 13 | return false 14 | } 15 | } 16 | return true 17 | } 18 | -------------------------------------------------------------------------------- /sort/3way_quick.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | import "github.com/maximelamure/algorithms/common" 4 | 5 | type threeWayQuickSort struct { 6 | } 7 | 8 | func New3WayQuickSort() Sorter { 9 | return &threeWayQuickSort{} 10 | } 11 | 12 | func (s *threeWayQuickSort) Sort(arr []int) { 13 | s.threeWayQuickSort(arr, 0, len(arr)-1) 14 | } 15 | 16 | func (s *threeWayQuickSort) threeWayQuickSort(arr []int, lo, hi int) { 17 | if lo >= hi { 18 | return 19 | } 20 | 21 | lt := lo 22 | gt := hi 23 | v := arr[lo] 24 | i := lo 25 | 26 | for { 27 | if i > gt { 28 | break 29 | } 30 | if v > arr[i] { 31 | common.Swap(arr, lt, i) 32 | lt++ 33 | i++ 34 | } else if v < arr[i] { 35 | common.Swap(arr, i, gt) 36 | gt-- 37 | } else { 38 | i++ 39 | } 40 | } 41 | s.threeWayQuickSort(arr, lo, lt-1) 42 | s.threeWayQuickSort(arr, gt+1, hi) 43 | 44 | } 45 | -------------------------------------------------------------------------------- /sort/bubblesort.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | import "github.com/maximelamure/algorithms/common" 4 | 5 | // bubleSort implements the Buble Sort 6 | // We start at the begining of the array. and swap the first two elements if 7 | // the first is greater than the second 8 | // Runtime O(n2) average and worst case. Memory: O(1) 9 | 10 | type bubbleSort struct { 11 | } 12 | 13 | func NewBubbleSort() Sorter { 14 | return &bubbleSort{} 15 | } 16 | 17 | func (s *bubbleSort) Sort(arr []int) { 18 | for _ = range arr { 19 | for i := 0; i < len(arr)-1; i++ { 20 | if arr[i] > arr[i+1] { 21 | common.Swap(arr, i, i+1) 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /sort/heap.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | import "github.com/maximelamure/algorithms/common" 4 | 5 | // Heap construction uses <= 2N compares and exchanges 6 | // heapSort uses <= 2 N lg N compares and exchanges 7 | // heapSort is optimal for both time and space, but : 8 | // - Inner loop longer than quickSort's 9 | // - Makes poor use of cache memory 10 | // - Not stable 11 | // worst: 2 N lg N , average: 2 N lg N , best: N lg N 12 | // N log N guarantee , in place 13 | type heapSort struct{} 14 | 15 | func NewHeapSort() Sorter { 16 | return &heapSort{} 17 | } 18 | 19 | func (h *heapSort) Sort(arr []int) { 20 | //create a binay heap 21 | N := len(arr) - 1 22 | for x := N / 2; x >= 1; x-- { 23 | h.Sink(arr, x, N) 24 | } 25 | // Delete the max 26 | 27 | for { 28 | if N <= 1 { 29 | break 30 | } 31 | common.Swap(arr, 1, N) 32 | N-- 33 | h.Sink(arr, 1, N) 34 | } 35 | } 36 | 37 | // Sink builds a Max heap using bottom-up method 38 | func (h *heapSort) Sink(arr []int, k, N int) { 39 | for { 40 | if k > N/2 { 41 | break 42 | } 43 | j := 2 * k 44 | if j < N && arr[j] < arr[j+1] { 45 | j++ 46 | } 47 | if arr[k] < arr[j] { 48 | common.Swap(arr, k, j) 49 | k = j 50 | } else { 51 | break 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /sort/insertion.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | import "github.com/maximelamure/algorithms/common" 4 | 5 | // insertion Sort implement the Insertion Sort 6 | // In iteration i, swap a[i] with each larger entry to its left 7 | // Runtime O(n2) average and worst case. Memory: O(1) 8 | 9 | type insertionSort struct { 10 | } 11 | 12 | func NewInsertionSort() Sorter { 13 | return &insertionSort{} 14 | } 15 | 16 | func (s *insertionSort) Sort(arr []int) { 17 | for x := 1; x < len(arr); x++ { 18 | for y := x; y > 0; y-- { 19 | if arr[y] < arr[y-1] { 20 | common.Swap(arr, y, y-1) 21 | } else { 22 | break 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sort/merge.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | // mergeSort implements the Merge Sort: 4 | // - Divide array into two values 5 | // - Recusrively sort each half 6 | // - Merge two halves 7 | // Runtime O(nln(n)) average and worst case. Memory: 2N 8 | // Uses at most Nln(N) compares and 6N ln(N) array access to sort 9 | // 10 | // User insertion Sort for small subarrays 11 | // - MergeSort has too much overhead for tiny subarrays 12 | // - Cutoff to insertion for ~ 7 items 13 | 14 | type mergeSort struct { 15 | aux []int 16 | } 17 | 18 | func NewMergeSort() Sorter { 19 | return &mergeSort{} 20 | } 21 | 22 | func (s *mergeSort) Sort(arr []int) { 23 | s.aux = make([]int, len(arr)) 24 | s.mergeSort(arr, 0, len(arr)-1) 25 | } 26 | 27 | func (s *mergeSort) mergeSort(arr []int, low, high int) { 28 | if low < high { 29 | med := low + (high-low)/2 30 | s.mergeSort(arr, low, med) 31 | s.mergeSort(arr, med+1, high) 32 | if arr[med] < arr[med+1] { // optim. If true, the left and right sub array are already ordered 33 | return 34 | } 35 | s.merge(arr, low, med, high) 36 | } 37 | } 38 | 39 | func (s *mergeSort) merge(arr []int, low, med, heigh int) { 40 | //copy to the aux array 41 | for x := low; x <= heigh; x++ { 42 | s.aux[x] = arr[x] 43 | } 44 | 45 | // merge logic 46 | ileft := low 47 | iright := med + 1 48 | 49 | for i := low; i <= heigh; i++ { 50 | if ileft > med { 51 | arr[i] = s.aux[iright] 52 | iright++ 53 | } else if iright > heigh { 54 | arr[i] = s.aux[ileft] 55 | ileft++ 56 | } else if s.aux[ileft] < s.aux[iright] { 57 | arr[i] = s.aux[ileft] 58 | ileft++ 59 | } else { 60 | arr[i] = s.aux[iright] 61 | iright++ 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /sort/merge_bottom.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | type mergeButtonSort struct { 4 | aux []int 5 | } 6 | 7 | func NewMergeBottomSort() Sorter { 8 | return &mergeButtonSort{} 9 | } 10 | 11 | func (s *mergeButtonSort) Sort(arr []int) { 12 | s.aux = make([]int, len(arr)) 13 | for sz := 1; sz < len(arr); sz = sz + sz { 14 | for lo := 0; lo < len(arr)-sz; lo += sz + sz { 15 | s.merge(arr, lo, lo+sz-1, Min(lo+sz+sz-1, len(arr)-1)) 16 | } 17 | } 18 | } 19 | 20 | func (s *mergeButtonSort) merge(arr []int, low, med, heigh int) { 21 | //copy to the aux array 22 | for x := low; x <= heigh; x++ { 23 | s.aux[x] = arr[x] 24 | } 25 | 26 | // merge logic 27 | ileft := low 28 | iright := med + 1 29 | 30 | for i := low; i <= heigh; i++ { 31 | if ileft > med { 32 | arr[i] = s.aux[iright] 33 | iright++ 34 | } else if iright > heigh { 35 | arr[i] = s.aux[ileft] 36 | ileft++ 37 | } else if s.aux[ileft] < s.aux[iright] { 38 | arr[i] = s.aux[ileft] 39 | ileft++ 40 | } else { 41 | arr[i] = s.aux[iright] 42 | iright++ 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /sort/quick.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | type quickSort struct{} 4 | 5 | func NewQuickSort() Sorter { 6 | return &quickSort{} 7 | } 8 | 9 | func (s *quickSort) Sort(arr []int) { 10 | su := NewShuffle() 11 | su.Sort(arr) //Shuffle to avoid the worst case 12 | s.quickSort(arr, 0, len(arr)-1) 13 | } 14 | 15 | func (s *quickSort) quickSort(arr []int, lo, hi int) { 16 | if hi <= lo { 17 | return 18 | } 19 | p := Partition(arr, lo, hi) 20 | s.quickSort(arr, lo, p-1) 21 | s.quickSort(arr, p+1, hi) 22 | } 23 | -------------------------------------------------------------------------------- /sort/select.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | // QuickSelect returns the kth largest item in the given array 4 | func QuickSelect(a []int, k int) int { 5 | if k > len(a)-1 { 6 | return -1 7 | } 8 | 9 | //Shuffle 10 | sh := NewShuffle() 11 | sh.Sort(a) 12 | 13 | i := 0 14 | j := len(a) - 1 15 | 16 | for { 17 | if i < j { 18 | n := Partition(a, i, j) 19 | if n > k { 20 | j = n - 1 21 | } else if n < k { 22 | i = n + 1 23 | } else { 24 | return a[n] 25 | } 26 | } else { 27 | return a[k] 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /sort/selection.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | import "github.com/maximelamure/algorithms/common" 4 | 5 | // Selection Sort implements the Selection Sort 6 | // In iteration i, Find the smallest element using a linear scan and 7 | // move it to the front (Swap a[i] and a[min]) 8 | // Runtime O(n^2) average and worst case. Memory: O(1) 9 | 10 | type selectionSort struct { 11 | } 12 | 13 | func NewSelectionSort() Sorter { 14 | return &selectionSort{} 15 | } 16 | 17 | func (s *selectionSort) Sort(arr []int) { 18 | for x := range arr { 19 | min := x 20 | for y := x; y < len(arr); y++ { 21 | if arr[y] < arr[min] { 22 | min = y 23 | } 24 | } 25 | common.Swap(arr, x, min) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sort/shell.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | import "github.com/maximelamure/algorithms/common" 4 | 5 | // Shell Sort is a custom insertion Sort 6 | // Move entries more than one position at a time by h-sorting the array 7 | // The worst case number of compares with the 3x+1 increments is O(n^2/3) 8 | type shellSort struct { 9 | } 10 | 11 | func NewShellSort() Sorter { 12 | return &shellSort{} 13 | } 14 | 15 | func (s *shellSort) Sort(arr []int) { 16 | h := 1 17 | // Compute H with the rule 3x+1 18 | for { 19 | if h > len(arr)/3 { 20 | break 21 | } 22 | h = 3*h + 1 23 | } 24 | 25 | for { 26 | if h < 1 { 27 | break 28 | } 29 | 30 | // insertionSort 31 | for i := h; i < len(arr); i++ { 32 | for j := i; j >= h && arr[j] < arr[j-h]; j -= h { 33 | common.Swap(arr, j, j-h) 34 | } 35 | } 36 | 37 | h = h / 3 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sort/shuffle.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | 7 | "github.com/maximelamure/algorithms/common" 8 | ) 9 | 10 | type Shuffle struct { 11 | } 12 | 13 | func NewShuffle() *Shuffle { 14 | return &Shuffle{} 15 | } 16 | 17 | func (s *Shuffle) Sort(arr []int) { 18 | rand.Seed(time.Now().Unix()) 19 | for i := 1; i < len(arr); i++ { 20 | s := rand.Intn(i) 21 | common.Swap(arr, i, s) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sort/sort.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | import "github.com/maximelamure/algorithms/common" 4 | 5 | type Sorter interface { 6 | Sort(a []int) 7 | } 8 | 9 | func Min(a, b int) int { 10 | if a <= b { 11 | return a 12 | } 13 | return b 14 | } 15 | 16 | func Partition(arr []int, lo, hi int) int { 17 | i := lo 18 | j := hi 19 | pivot := lo 20 | for { 21 | 22 | for { 23 | if i >= hi || arr[i] > arr[pivot] { 24 | break 25 | } 26 | i++ 27 | } 28 | for { 29 | if j <= lo || arr[j] < arr[pivot] { 30 | break 31 | } 32 | j-- 33 | } 34 | if i >= j { 35 | break 36 | } 37 | 38 | common.Swap(arr, i, j) 39 | } 40 | common.Swap(arr, pivot, j) 41 | return j 42 | } 43 | -------------------------------------------------------------------------------- /sort/sort_test.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/maximelamure/algorithms/common" 8 | ) 9 | 10 | func GetRandomArray() []int { 11 | return []int{5, 3, 6, 10, 7, 8, 4, 5, 6, 3, 8, 4, 6, 2, 1, 7} 12 | } 13 | 14 | func Test_QuickSelect2(t *testing.T) { 15 | helper := common.Test{} 16 | array := []int{5, 3, 6, 10, 7, 8, 4, 5, 6} 17 | helper.Assert(t, QuickSelect(array, 1) == 4, "Error") 18 | } 19 | 20 | func Test_Selection(t *testing.T) { 21 | s := NewSelectionSort() 22 | testSort(s, t) 23 | } 24 | 25 | func Test_Insertion(t *testing.T) { 26 | s := NewInsertionSort() 27 | testSort(s, t) 28 | } 29 | 30 | func Test_Bubble(t *testing.T) { 31 | s := NewBubbleSort() 32 | testSort(s, t) 33 | } 34 | 35 | func Test_ShellSort(t *testing.T) { 36 | s := NewShellSort() 37 | testSort(s, t) 38 | } 39 | 40 | func Test_MergeSort(t *testing.T) { 41 | s := NewMergeSort() 42 | testSort(s, t) 43 | } 44 | 45 | func Test_MergeButtonSort(t *testing.T) { 46 | s := NewMergeBottomSort() 47 | testSort(s, t) 48 | } 49 | 50 | func Test_QuickSort(t *testing.T) { 51 | s := NewQuickSort() 52 | testSort(s, t) 53 | } 54 | 55 | func Test_3WayQuickSort(t *testing.T) { 56 | s := New3WayQuickSort() 57 | testSort(s, t) 58 | } 59 | 60 | func Test_HeapSort(t *testing.T) { 61 | helper := common.Test{} 62 | array := []int{60, 50, 40, 38, 43, 36, 22} 63 | su := NewShuffle() 64 | su.Sort(array) 65 | array = append(array, 0) 66 | common.Swap(array, 0, len(array)-1) 67 | fmt.Println(array) 68 | s := NewHeapSort() 69 | s.Sort(array) 70 | fmt.Println(array) 71 | helper.Assert(t, Sorted(array), "The array is not sorted ") 72 | } 73 | 74 | func Test_Shuffle(t *testing.T) { 75 | helper := common.Test{} 76 | array := GetRandomArray() 77 | s := NewInsertionSort() 78 | s.Sort(array) 79 | helper.Assert(t, Sorted(array), "The array is not sorted ") 80 | fmt.Println(array) 81 | su := NewShuffle() 82 | su.Sort(array) 83 | fmt.Println(array) 84 | helper.Assert(t, !Sorted(array), "The array is sorted ") 85 | } 86 | 87 | func testSort(s Sorter, t *testing.T) { 88 | helper := common.Test{} 89 | array := GetRandomArray() 90 | s.Sort(array) 91 | fmt.Println(array) 92 | helper.Assert(t, Sorted(array), "The array is not sorted ") 93 | } 94 | 95 | func Sorted(arr []int) bool { 96 | sorted := true 97 | for i := range arr { 98 | if i != 0 && arr[i] < arr[i-1] { 99 | sorted = false 100 | break 101 | } 102 | } 103 | return sorted 104 | } 105 | -------------------------------------------------------------------------------- /unionfind/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maximelamure/algorithms/d7cfe2f2953cf79c2dfc03152a92ac9e4635d45c/unionfind/.DS_Store -------------------------------------------------------------------------------- /unionfind/pathcompression.go: -------------------------------------------------------------------------------- 1 | package unionfind 2 | 3 | // Path Compression is an improved Weighted QuickUnion 4 | // - Just after computing the root of p, set the id of each examined node to 5 | // point to that root. 6 | 7 | type pathCompression struct { 8 | IDs []int 9 | Weights []int 10 | } 11 | 12 | // NewPathCompression initialize a new Path Compression structure 13 | func NewPathCompression(n int) *pathCompression { 14 | result := &pathCompression{} 15 | result.IDs = make([]int, n) 16 | result.Weights = make([]int, n) 17 | for x := range result.IDs { 18 | result.IDs[x] = x 19 | result.Weights[x] = 1 20 | } 21 | return result 22 | } 23 | 24 | // Root returns the root of r 25 | func (q *pathCompression) Root(r int) int { 26 | for { 27 | if r == q.IDs[r] { 28 | break 29 | } 30 | q.IDs[r] = q.IDs[q.IDs[r]] 31 | r = q.IDs[r] 32 | } 33 | return r 34 | } 35 | 36 | // Connectect check if p and r have the same root. 37 | // - true: they are connected 38 | // - false: the are not connected 39 | func (q *pathCompression) Connected(p, r int) bool { 40 | return q.Root(p) == q.Root(r) 41 | } 42 | 43 | // Union merges p and r by linking root of smaller tree to root of larger tree 44 | func (q *pathCompression) Union(p, r int) { 45 | qr := q.Root(r) 46 | qp := q.Root(p) 47 | if qr == qp { 48 | return 49 | } 50 | 51 | if q.Weights[qr] > q.Weights[qp] { 52 | q.IDs[qp] = qr 53 | q.Weights[qr] += q.Weights[qp] 54 | } else { 55 | q.IDs[qr] = qp 56 | q.Weights[qp] += q.Weights[qr] 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /unionfind/pathcompression_test.go: -------------------------------------------------------------------------------- 1 | package unionfind 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/maximelamure/algorithms/common" 7 | ) 8 | 9 | func TestPathCompression(t *testing.T) { 10 | qf := NewPathCompression2(10) 11 | qf.Union(1, 4) 12 | qf.Union(0, 3) 13 | helper := common.Test{} 14 | helper.Assert(t, qf.Connected(1, 4), "4 and 1 should be connected") 15 | helper.Assert(t, !qf.Connected(1, 3), "3 and 1 should not be connected") 16 | qf.Union(1, 3) 17 | helper.Assert(t, qf.Connected(1, 3), "3 and 1 should not be connected") 18 | } 19 | -------------------------------------------------------------------------------- /unionfind/quickfind.go: -------------------------------------------------------------------------------- 1 | package unionfind 2 | 3 | import "fmt" 4 | 5 | // QuickFind is a data structure 6 | // - Interger array id[] of size N 7 | // - Interpretation: p and q are connected if and only if thay have the same id 8 | type quickFind struct { 9 | IDs []int 10 | } 11 | 12 | // NewQuickFind initialize a new QuickFind structure 13 | func NewQuickFind(n int) *quickFind { 14 | result := &quickFind{} 15 | result.IDs = make([]int, n) 16 | for x := range result.IDs { 17 | result.IDs[x] = x 18 | } 19 | return result 20 | } 21 | 22 | // Connected check if p and r have the same id. 23 | // - true: they are connected 24 | // - false: they are not connected 25 | func (q *quickFind) Connected(p, r int) bool { 26 | return q.IDs[p] == q.IDs[r] 27 | } 28 | 29 | // Union create an union between p and r. To merge components containing p and q 30 | // change all entries whose id equals id[p] to id[q] 31 | func (q *quickFind) Union(p, r int) { 32 | pid := q.IDs[p] 33 | rid := q.IDs[r] 34 | for x := range q.IDs { 35 | if q.IDs[x] == pid { 36 | q.IDs[x] = rid 37 | } 38 | } 39 | } 40 | 41 | // String prints the IDs array 42 | func (q *quickFind) String() { 43 | fmt.Println("QuickFind") 44 | for x := range q.IDs { 45 | fmt.Print(q.IDs[x], " ") 46 | } 47 | fmt.Println(" ") 48 | } 49 | -------------------------------------------------------------------------------- /unionfind/quickfinduf_test.go: -------------------------------------------------------------------------------- 1 | package unionfind 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/maximelamure/algorithms/common" 7 | ) 8 | 9 | func TestQuickFind(t *testing.T) { 10 | qf := NewQuickFind(10) 11 | qf.Union(1, 4) 12 | qf.Union(0, 3) 13 | helper := common.Test{} 14 | helper.Assert(t, qf.Connected(1, 4), "4 and 1 should be connected") 15 | helper.Assert(t, !qf.Connected(1, 3), "3 and 1 should not be connected") 16 | qf.Union(1, 3) 17 | helper.Assert(t, qf.Connected(1, 3), "3 and 1 should not be connected") 18 | } 19 | -------------------------------------------------------------------------------- /unionfind/quickunion.go: -------------------------------------------------------------------------------- 1 | package unionfind 2 | 3 | // QuickUnion is a data structure 4 | // - Interger array id[] of size N 5 | // - Interpretation: id[i] is parent of i 6 | // - Root of i is id[id[id[... id[i]...]]] 7 | 8 | type quickUnion struct { 9 | IDs []int 10 | } 11 | 12 | // NewQuickUnion initialize a new QuickUnion structure 13 | func NewQuickUnion(n int) *quickUnion { 14 | result := &quickUnion{} 15 | result.IDs = make([]int, n) 16 | for x := range result.IDs { 17 | result.IDs[x] = x 18 | } 19 | return result 20 | } 21 | 22 | // Root returns the root of r 23 | func (q *quickUnion) Root(r int) int { 24 | for { 25 | if r == q.IDs[r] { 26 | break 27 | } 28 | r = q.IDs[r] 29 | } 30 | return r 31 | } 32 | 33 | // Root returns the root of r (recursive version) 34 | func (q *quickUnion) RootRec(p int) int { 35 | for { 36 | if p == q.IDs[p] { 37 | return p 38 | } else { 39 | return q.RootRec(q.IDs[p]) 40 | } 41 | } 42 | } 43 | 44 | // Connectect check if p and r have the same root. 45 | // - true: they are connected 46 | // - false: the are not connected 47 | func (q *quickUnion) Connected(p, r int) bool { 48 | return q.Root(p) == q.Root(r) 49 | } 50 | 51 | // Union merges p and r by setting the id of p's root to the id of r's root 52 | func (q *quickUnion) Union(p, r int) { 53 | q.IDs[q.Root(r)] = q.Root(p) 54 | } 55 | -------------------------------------------------------------------------------- /unionfind/quickunion_test.go: -------------------------------------------------------------------------------- 1 | package unionfind 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/maximelamure/algorithms/common" 7 | ) 8 | 9 | func TestQuickUnion(t *testing.T) { 10 | qf := NewQuickUnion(10) 11 | qf.Union(1, 4) 12 | qf.Union(0, 3) 13 | helper := common.Test{} 14 | helper.Assert(t, qf.Connected(1, 4), "4 and 1 should be connected") 15 | helper.Assert(t, !qf.Connected(1, 3), "3 and 1 should not be connected") 16 | qf.Union(1, 3) 17 | helper.Assert(t, qf.Connected(1, 3), "3 and 1 should not be connected") 18 | } 19 | -------------------------------------------------------------------------------- /unionfind/weightedqu.go: -------------------------------------------------------------------------------- 1 | package unionfind 2 | 3 | import "fmt" 4 | 5 | // WeightedQU is a QuickUnion to avoid tall trees 6 | // - Keep track of size of each tree 7 | // - Balance by linking root of smaller tree to root of larger tree 8 | 9 | type weightedQU struct { 10 | IDs []int 11 | Weights []int 12 | } 13 | 14 | // NewWeightedQU initialize a new Weighted QuickUnion structure 15 | func NewWeightedQU(n int) *weightedQU { 16 | result := &weightedQU{} 17 | result.IDs = make([]int, n) 18 | result.Weights = make([]int, n) 19 | for x := range result.IDs { 20 | result.IDs[x] = x 21 | result.Weights[x] = 1 22 | } 23 | return result 24 | } 25 | 26 | // Root returns the root of r 27 | func (q *weightedQU) Root(r int) int { 28 | for { 29 | if r == q.IDs[r] { 30 | break 31 | } 32 | r = q.IDs[r] 33 | } 34 | return r 35 | } 36 | 37 | // Connectect check if p and r have the same root. 38 | // - true: they are connected 39 | // - false: the are not connected 40 | func (q *weightedQU) Connected(p, r int) bool { 41 | return q.Root(p) == q.Root(r) 42 | } 43 | 44 | // Union merges p and r by linking root of smaller tree to root of larger tree 45 | func (q *weightedQU) Union(p, r int) { 46 | qr := q.Root(r) 47 | qp := q.Root(p) 48 | if qr == qp { 49 | return 50 | } 51 | 52 | if q.Weights[qr] > q.Weights[qp] { 53 | q.IDs[qp] = qr 54 | q.Weights[qr] += q.Weights[qp] 55 | } else { 56 | q.IDs[qr] = qp 57 | q.Weights[qp] += q.Weights[qr] 58 | } 59 | 60 | } 61 | 62 | func (q *weightedQU) String() { 63 | fmt.Println("WeightedQU") 64 | for x := range q.IDs { 65 | fmt.Print(q.IDs[x], " ") 66 | } 67 | fmt.Println(" ") 68 | } 69 | -------------------------------------------------------------------------------- /unionfind/weightedqu_test.go: -------------------------------------------------------------------------------- 1 | package unionfind 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/maximelamure/algorithms/common" 7 | ) 8 | 9 | func TestWeightedQU(t *testing.T) { 10 | qf := NewWeightedQU2(10) 11 | qf.Union(1, 4) 12 | qf.Union(0, 3) 13 | helper := common.Test{} 14 | helper.Assert(t, qf.Connected(1, 4), "4 and 1 should be connected") 15 | helper.Assert(t, !qf.Connected(1, 3), "3 and 1 should not be connected") 16 | qf.Union(1, 3) 17 | helper.Assert(t, qf.Connected(1, 3), "3 and 1 should not be connected") 18 | } 19 | --------------------------------------------------------------------------------