Implement data structures with Go.
The package provides six iterators as following.
ValueIterator traverses the value backward.
typeValueIteratorinterface {
Next() boolBegin()
Value() interface{}
}ReverseValueIterator can traverse values forward or backward.
typeReverseValueIteratorinterface {
ValueIteratorPrev() boolEnd()
}IndexIterator traverses the index-value pair backward.
typeIndexIteratorinterface {
ValueIteratorIndex() int
}ReverseIndexIterator can traverse the index-value pair forward or backward.
typeReverseIndexIteratorinterface {
IndexIteratorPrev() boolEnd()
}KeyIterator traverses the key-value pair backward.
typeKeyIteratorinterface {
ValueIteratorKey() interface{}
}ReverseKeyIterator can traverse the key-value pair forward or backward.
typeReverseKeyIteratorinterface {
KeyIteratorPrev() boolEnd()
}Different data structures have different support for iterator as following.
All data structures will implement the Container interface.
typeContainerinterface {
Empty() boolSize() intClear()
Values() []interface{}
}List is ordered and value repeatable.
Implements Container interface.
typeListinterface {
Append(values...interface{})
Get(indexint) (interface{}, error)
Remove(indexint) errorContains(values...interface{}) boolSwap(i, jint) errorInsert(indexint, values...interface{}) errorSet(indexint, valueinterface{}) errorIndexOf(valueinterface{}) (int, error)
container.Container// Empty() bool// Size() int// Clear()// Values() []interface{}
}The current element of SinglyLinkedList points to the next element.
Implements List, ValueIterator and IndexIterator interface.
package main
import (
"fmt""github.com/prprprus/ds/list/singlylinkedlist"
)
funcmain() {
list:=singlylinkedlist.New() // []list.Append(1) // [1]list.Append(2) // [1, 2]list.Append(3) // [1, 2, 3]list.PreAppend(4) // [4, 1, 2, 3]_, _=list.Get(0) // 4, nil_, _=list.Get(999) // nil, ErrIndex_=list.Remove(2) // [4, 1, 3]_=list.Contains() // true_=list.Contains(4, 1) // true_=list.Contains(4, 3) // true_=list.Contains(4, 1, 3, 5) // false_=list.Swap(0, 1) // [1, 4, 3]_=list.Insert(1, 5, 6, 7, 8) // [1, 4, 5, 6, 7, 8, 3]_=list.Set(3, -1) // [1, 4, 5, -1, 7, 8, 3]// iteratorit:=list.Iterator()
it.Begin()
forit.Next() {
fmt.Println(it.Index(), it.Value())
}
// output:// 0 1// 1 4// 2 5// 3 -1// 4 7// 5 8// 6 3_, _=list.IndexOf(1) // 0, nil_, _=list.IndexOf(8) // 5, nil_, _=list.IndexOf(100) // -1, ErrIndexOflist.Reverse() // [3, 8, 7, -1, 5, 4, 1]_=list.Empty() // false_=list.Size() // 7_=list.Values() // [3 8 7 -1 5 4 1]list.Clear() // []
}The current and next elements of the DoubleLinkedList point to each other.
Implements List, ValueIterator, ReverseValueIterator, IndexIterator and ReverseIndexIterator interface.
package main
import (
"fmt""github.com/prprprus/ds/list/doublelinkedlist"
)
funcmain() {
list:=doublelinkedlist.New() // []list.Append(1) // [1]list.Append(2) // [1 2]list.Append(3) // [1 2 3]list.PreAppend(4) // [4 1 2 3]_, _=list.Get(0) // 4, nil_, _=list.Get(999) // nil, ErrIndex_=list.Remove(2) // [4 1 3]_=list.Contains() // true_=list.Contains(4, 1) // true_=list.Contains(4, 3) // true_=list.Contains(4, 1, 3, 5) // false_=list.Swap(0, 1) // [1 4 3]_=list.Insert(1, 5, 6, 7, 8) // [1 4 5 6 7 8 3]_=list.Set(3, -1) // [1 4 5 -1 7 8 3]// iteratorit:=list.Iterator()
it.Begin()
forit.Next() {
fmt.Println(it.Index(), it.Value())
}
// output:// 0 1// 1 4// 2 5// 3 -1// 4 7// 5 8// 6 3it.End()
forit.Prev() {
fmt.Println(it.Index(), it.Value())
}
// output:// 6 3// 5 8// 4 7// 3 -1// 2 5// 1 4// 0 1_, _=list.IndexOf(1) // 0, nil_, _=list.IndexOf(8) // 5, nil_, _=list.IndexOf(100) // -1, ErrIndexOflist.Reverse() // [3 8 7 -1 5 4 1]_=list.Empty() // false_=list.Size() // 7_=list.Values() // [3 8 7 -1 5 4 1]list.Clear() // []
}ArrayList is a dynamic array that can be dynamically scaled based on capacity and number of elements.
Implements List, ValueIterator, ReverseValueIterator, IndexIterator and ReverseIndexIterator interface.
package main
import (
"fmt""github.com/prprprus/ds/list/arraylist"
)
funcmain() {
list:=arraylist.New() // []list.Append(1) // [1]list.Append(2) // [1 2]list.Append(3) // [1 2 3]_, _=list.Get(0) // 1, nil_, _=list.Get(999) // nil, ErrIndex_=list.Remove(2) // [1 2]_=list.Contains() // true_=list.Contains(1, 2) // true_=list.Contains(2) // true_=list.Contains(1, 2, 3) // false_=list.Swap(0, 1) // [2 1]_=list.Insert(1, 5, 6, 7, 8) // [2 1 5 6 7 8]_=list.Set(3, -1) // [2 1 5 -1 7 8]// iteratorit:=list.Iterator()
it.Begin()
forit.Next() {
fmt.Println(it.Index(), it.Value())
}
// output:// 0 2// 1 1// 2 5// 3 -1// 4 7// 5 8it.End()
forit.Prev() {
fmt.Println(it.Index(), it.Value())
}
// output:// 5 8// 4 7// 3 -1// 2 5// 1 1// 0 2_, _=list.IndexOf(1) // 1, nil_, _=list.IndexOf(8) // 5, nil_, _=list.IndexOf(100) // -1, ErrIndexOf_=list.Empty() // false_=list.Size() // 6_=list.Values() // [2 1 5 -1 7 8]list.Clear() // []
}Stack is a FILO data structure.
Implements Container interface.
typeStackinterface {
Push(valueinterface{})
Pop() (interface{}, error)
Peek() (interface{}, error)
container.Container// Empty() bool// Size() int// Clear()// Values() []interface{}
}LinkedListStack is a stack based on SinglyLinkedList.
Implements Stack, ValueIterator and IndexIterator interface.
package main
import (
"fmt""github.com/prprprus/ds/stack/linkedliststack"
)
funcmain() {
stack:=linkedliststack.New() // []stack.Push(1) // [1]stack.Push(2) // [2 1]stack.Push(3) // [3 2 1]// iteratorit:=stack.Iterator()
it.Begin()
forit.Next() {
fmt.Println(it.Index(), it.Value())
}
// output:// 0 3// 1 2// 2 1_, _=stack.Peek() // 3, nil_, _=stack.Pop() // 3, nil_, _=stack.Peek() // 2, nil_=stack.Empty() // false_=stack.Size() // 2_=stack.Values() // [2 1]stack.Clear() // []
}ArrayStack is a stack based on ArrayList.
Implements Stack, ValueIterator, ReverseValueIterator, IndexIterator and ReverseIndexIterator interface.
package main
import (
"fmt""github.com/prprprus/ds/stack/arraystack"
)
funcmain() {
stack:=arraystack.New() // []stack.Push(1) // [1]stack.Push(2) // [2 1]stack.Push(3) // [3 2 1]// iteratorit:=stack.Iterator()
it.Begin()
forit.Next() {
fmt.Println(it.Index(), it.Value())
}
// output:// 0 3// 1 2// 2 1_, _=stack.Peek() // 3, nil_, _=stack.Pop() // 3, nil_, _=stack.Peek() // 2, nil_=stack.Empty() // false_=stack.Size() // 2_=stack.Values() // [2 1]stack.Clear() // []
}Queue is a FIFO data structure.
Implements Container interface.
typeQueueinterface {
Put(valueinterface{})
Get() (interface{}, error)
container.Container// Empty() bool// Size() int// Clear()// Values() []interface{}
}LinkedListQueue is a stack based on SinglyLinkedList.
Implements Queue, ValueIterator and IndexIterator interface.
package main
import (
"fmt""github.com/prprprus/ds/queue/linkedlistqueue"
)
funcmain() {
queue:=linkedlistqueue.New() // []queue.Put(1) // [1]queue.Put(2) // [1 2]queue.Put(3) // [1 2 3]queue.Put(4) // [1 2 3 4]// iteratorit:=queue.Iterator()
it.Begin()
forit.Next() {
fmt.Println(it.Index(), it.Value())
}
// output:// 0 1// 1 2// 2 3// 3 4_, _=queue.Get() // 1, nil_, _=queue.Get() // 2, nil_=queue.Empty() // false_=queue.Size() // 2_=queue.Values() // [3 4]queue.Clear() // []
}ArrayQueue is a stack based on ArrayList.
Implements Queue, ValueIterator and IndexIterator interface.
package main
import (
"fmt""github.com/prprprus/ds/queue/arrayqueue"
)
funcmain() {
queue:=arrayqueue.New() // []queue.Put(1) // [1]queue.Put(2) // [1 2]queue.Put(3) // [1 2 3]queue.Put(4) // [1 2 3 4]// iteratorit:=queue.Iterator()
it.Begin()
forit.Next() {
fmt.Println(it.Index(), it.Value())
}
// output:// 0 1// 1 2// 2 3// 3 4_, _=queue.Get() // 1, nil_, _=queue.Get() // 2, nil_=queue.Empty() // false_=queue.Size() // 2_=queue.Values() // [3 4]queue.Clear() // []
}SkipList is a random data structure with performance comparable to that of red-black trees. It should be noted that the keys must be comparable types and element will be sorted by keys.
Implements Container, ValueIterator and KeyIterator interface.
package main
import (
"fmt""github.com/prprprus/ds/skiplist""github.com/prprprus/ds/util"
)
funcmain() {
skiplist:=skiplist.New(util.IntComparator) // []skiplist.Set(1, "a") // [{1: "a"}]skiplist.Set(2, "b") // [{1: "a"} {2: "b"}]skiplist.Set(3, "c") // [{1: "a"} {2: "b"} {3: "c"}]skiplist.Set(4, "d") // [{1: "a"} {2: "b"} {3: "c"} {4: "d"}]// iteratorit:=skiplist.Iterator()
it.Begin()
forit.Next() {
fmt.Println(it.Key(), it.Value())
}
// output:// 1 a// 2 b// 3 c// 4 d_=skiplist.Exists(1) // true_=skiplist.Exists(9) // false_, _=skiplist.Get(1) // "a", nil_, _=skiplist.Get(3) // "c", nil_=skiplist.Remove(2) // nil_=skiplist.Keys() // [1 3 4]_=skiplist.Empty() // false_=skiplist.Size() // 3_=skiplist.Values() // [a c d]skiplist.Clear() // []
}Map stores key-value pairs with excellent operational performance. It should be noted that the keys must be comparable types.
Implements Container interface.
typeMapinterface {
Put(key, valueinterface{})
Get(keyinterface{}) (interface{}, error)
Remove(keyinterface{})
container.Container// Empty() bool// Size() int// Clear()// Values() []interface{}
}HashMap is a map based on hash table.
Implements Map interface.
package main
import (
"github.com/prprprus/ds/maps/hashmap"
)
funcmain() {
m:=hashmap.New() // []m.Put(1, "a") // [{1: "a"}]m.Put(2, "b") // [{1: "a"} {2: "b"}]m.Put(3, "c") // [{1: "a"} {2: "b"} {3: "c"}]m.Put(4, "d") // [{1: "a"} {2: "b"} {3: "c"} {4: "d"}]_=m.Keys() // [1 2 3 4] (Note: order of random)_, _=m.Get(1) // "a", nil_, _=m.Get(3) // "c", nil_=m.Remove(2) // nil_=m.Keys() // [1 3 4]_=m.Empty() // false_=m.Size() // 3_=m.Values() // [a c d] (Note: order of random)m.Clear() // []
}LinkedHashMap is a map based on hash table and DoubleLinkedList, it provides ordered key-value pairs.
Implements Map, ValueIterator, ReverseValueIterator, KeyIterator and ReverseKeyIterator interface.
package main
import (
"fmt""github.com/prprprus/ds/maps/linkedhashmap"
)
funcmain() {
m:=linkedhashmap.New() // []m.Put(1, "a") // [{1: "a"}]m.Put(2, "b") // [{1: "a"} {2: "b"}]m.Put(3, "c") // [{1: "a"} {2: "b"} {3: "c"}]m.Put(4, "d") // [{1: "a"} {2: "b"} {3: "c"} {4: "d"}]// iteratorit:=m.Iterator()
it.Begin()
forit.Next() {
fmt.Println(it.Key(), it.Value())
}
// output:// 1 a// 2 b// 3 c// 4 dit.End()
forit.Prev() {
fmt.Println(it.Key(), it.Value())
}
// output:// 4 d// 3 c// 2 b// 1 a_=m.Keys() // [1 2 3 4]_, _=m.Get(1) // "a", nil_, _=m.Get(3) // "c", nil_=m.Remove(2) // nil_=m.Keys() // [1 3 4]_=m.Empty() // false_=m.Size() // 3_=m.Values() // [a c d]m.Clear() // []
}SkipMap is a map based on SkipList.
Implements Map, ValueIterator and KeyIterator.
package main
import (
"fmt""github.com/prprprus/ds/maps/linkedhashmap"
)
funcmain() {
m:=linkedhashmap.New() // []m.Put(1, "a") // [{1: "a"}]m.Put(2, "b") // [{1: "a"} {2: "b"}]m.Put(3, "c") // [{1: "a"} {2: "b"} {3: "c"}]m.Put(4, "d") // [{1: "a"} {2: "b"} {3: "c"} {4: "d"}]// iteratorit:=m.Iterator()
it.Begin()
forit.Next() {
fmt.Println(it.Key(), it.Value())
}
// output:// 1 a// 2 b// 3 c// 4 d_=m.Keys() // [1 2 3 4]_, _=m.Get(1) // "a", nil_, _=m.Get(3) // "c", nil_=m.Remove(2) // nil_=m.Keys() // [1 3 4]_=m.Empty() // false_=m.Size() // 3_=m.Values() // [a c d]m.Clear() // []
}Set is used to store non-repeating values, usually with good operational performance.
Implements Container interface.
typeSetinterface {
Add(values...interface{})
Remove(values...interface{}) errorContains(values...interface{}) bool
container.Container// Empty() bool// Size() int// Clear()// Values() []interface{}
}HashSet is a set based on hash table.
Implements Set interface.
package main
import (
"github.com/prprprus/ds/set/hashset"
)
funcmain() {
s:=hashset.New() // []s.Add(1) // [1]s.Add(2) // [1 2]s.Add(3) // [1 2 3]_=s.Contains() // true_=s.Contains(1, 2, 3) // true_=s.Contains(1, 3) // true_=s.Contains(2, 3, 4) // false_=s.Remove(2) // nil_=s.Empty() // false_=s.Size() // 2_=s.Values() // [1 3]s.Clear() // []
}LinkedHashSet is a set based on hash table and DoubleLinkedList, it provides ordered value.
Implements Set, ValueIterator and ReverseValueIterator interface.
package main
import (
"fmt""github.com/prprprus/ds/set/linkedhashset"
)
funcmain() {
s:=linkedhashset.New() // []s.Add(1) // [1]s.Add(2) // [1 2]s.Add(3) // [1 2 3]// iteratorit:=s.Iterator()
it.Begin()
forit.Next() {
fmt.Println(it.Value())
}
// output:// 1// 2// 3it.End()
forit.Prev() {
fmt.Println(it.Value())
}
// output:// 3// 2// 1_=s.Contains() // true_=s.Contains(1, 2, 3) // true_=s.Contains(1, 3) // true_=s.Contains(2, 3, 4) // false_=s.Remove(2) // nil_=s.Empty() // false_=s.Size() // 2_=s.Values() // [1 3]s.Clear() // []
}SkipSet is a set based on SkipList.
Implements Set and ValueIterator interface.
package main
import (
"fmt""github.com/prprprus/ds/set/skipset""github.com/prprprus/ds/util"
)
funcmain() {
s:=skipset.New(util.IntComparator) // []s.Add(1) // [1]s.Add(2) // [1 2]s.Add(3) // [1 2 3]// iteratorit:=s.Iterator()
it.Begin()
forit.Next() {
fmt.Println(it.Value())
}
// output:// 1// 2// 3_=s.Contains() // true_=s.Contains(1, 2, 3) // true_=s.Contains(1, 3) // true_=s.Contains(2, 3, 4) // false_=s.Remove(2) // nil_=s.Empty() // false_=s.Size() // 2_=s.Values() // [1 3]s.Clear() // []
}Contains some helper functions.
Comparator provides the following built-in type of comparator.
funcIntComparator(a, binterface{}) intfuncInt8Comparator(a, binterface{}) intfuncInt16Comparator(a, binterface{}) intfuncInt32Comparator(a, binterface{}) intfuncInt64Comparator(a, binterface{}) intfuncUIntComparator(a, binterface{}) intfuncUInt8Comparator(a, binterface{}) intfuncUInt16Comparator(a, binterface{}) intfuncUInt32Comparator(a, binterface{}) intfuncUInt64Comparator(a, binterface{}) intfuncFloat32Comparator(a, binterface{}) intfuncFloat64Comparator(a, binterface{}) intfuncByteComparator(a, binterface{}) intfuncRuneComparator(a, binterface{}) intfuncStringComparator(a, binterface{}) intThe meaning of the return value is as follows.
-1 => a < b
0 => a == b
1 => a > b
For custom types, you can also create a corresponding comparator.
package main
import (
"fmt""github.com/prprprus/ds/set/skipset"
)
typePeoplestruct {
namestringageint
}
funcAgeComparator(a, binterface{}) int {
c1:=a.(People)
c2:=b.(People)
switch {
casec1.age<c2.age:
return-1casec1.age>c2.age:
return1default:
return0
}
}
funcmain() {
s:=skipset.New(AgeComparator)
s.Add(People{"Wade", 35})
s.Add(People{"Simon", 32})
s.Add(People{"yiyi", 22})
fmt.Println(s.Values()) // [{"yiyi", 22}, {"Simon", 32}, {"Wade", 35}]
}go test -run=NO_TEST -bench=. -benchmem -benchtime 1s github.com/prprprus/ds/...













