Skip to content

prprprus/gds

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

build status go report godoc license

Introduction

Implement data structures with Go.

Table Of Content

Iterator

ValueIterator

The package provides six iterators as following.

ValueIterator traverses the value backward.

type ValueIterator interface {
	Next() bool
	Begin()
	Value() interface{}
}

ReverseValueIterator

ReverseValueIterator can traverse values forward or backward.

type ReverseValueIterator interface {
	ValueIterator

	Prev() bool
	End()
}

IndexIterator

IndexIterator traverses the index-value pair backward.

type IndexIterator interface {
	ValueIterator

	Index() int
}

ReverseIndexIterator

ReverseIndexIterator can traverse the index-value pair forward or backward.

type ReverseIndexIterator interface {
	IndexIterator

	Prev() bool
	End()
}

KeyIterator

KeyIterator traverses the key-value pair backward.

type KeyIterator interface {
	ValueIterator

	Key() interface{}
}

ReverseKeyIterator

ReverseKeyIterator can traverse the key-value pair forward or backward.

type ReverseKeyIterator interface {
	KeyIterator

	Prev() bool
	End()
}

Different data structures have different support for iterator as following.

ds1.png

Container

All data structures will implement the Container interface.

type Container interface {
	Empty() bool
	Size() int
	Clear()
	Values() []interface{}
}

List

List is ordered and value repeatable.

Implements Container interface.

type List interface {
	Append(values ...interface{})
	Get(index int) (interface{}, error)
	Remove(index int) error
	Contains(values ...interface{}) bool
	Swap(i, j int) error
	Insert(index int, values ...interface{}) error
	Set(index int, value interface{}) error
	IndexOf(value interface{}) (int, error)

	container.Container
	// Empty() bool
	// Size() int
	// Clear()
	// Values() []interface{}
}

SinglyLinkedList

The current element of SinglyLinkedList points to the next element.

Implements List, ValueIterator and IndexIterator interface.

drawing

package main

import (
	"fmt"

	"github.com/prprprus/ds/list/singlylinkedlist"
)

func main() {
	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]

	// iterator
	it := list.Iterator()
	it.Begin()
	for it.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, ErrIndexOf
	list.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()             // []
}

DoubleLinkedList

The current and next elements of the DoubleLinkedList point to each other.

Implements List, ValueIterator, ReverseValueIterator, IndexIterator and ReverseIndexIterator interface.

drawing

package main

import (
	"fmt"

	"github.com/prprprus/ds/list/doublelinkedlist"
)

func main() {
	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]

	// iterator
	it := list.Iterator()
	it.Begin()
	for it.Next() {
		fmt.Println(it.Index(), it.Value())
	}
	// output:
	// 0 1
	// 1 4
	// 2 5
	// 3 -1
	// 4 7
	// 5 8
	// 6 3
	it.End()
	for it.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, ErrIndexOf
	list.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

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.

drawing

package main

import (
	"fmt"

	"github.com/prprprus/ds/list/arraylist"
)

func main() {
	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]

	// iterator
	it := list.Iterator()
	it.Begin()
	for it.Next() {
		fmt.Println(it.Index(), it.Value())
	}
	// output:
	// 0 2
	// 1 1
	// 2 5
	// 3 -1
	// 4 7
	// 5 8
	it.End()
	for it.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

Stack is a FILO data structure.

Implements Container interface.

drawing

type Stack interface {
	Push(value interface{})
	Pop() (interface{}, error)
	Peek() (interface{}, error)

	container.Container
	// Empty() bool
	// Size() int
	// Clear()
	// Values() []interface{}
}

LinkedListStack

LinkedListStack is a stack based on SinglyLinkedList.

Implements Stack, ValueIterator and IndexIterator interface.

package main

import (
	"fmt"

	"github.com/prprprus/ds/stack/linkedliststack"
)

func main() {
	stack := linkedliststack.New() // []
	stack.Push(1)                  // [1]
	stack.Push(2)                  // [2 1]
	stack.Push(3)                  // [3 2 1]

	// iterator
	it := stack.Iterator()
	it.Begin()
	for it.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

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"
)

func main() {
	stack := arraystack.New() // []
	stack.Push(1)             // [1]
	stack.Push(2)             // [2 1]
	stack.Push(3)             // [3 2 1]

	// iterator
	it := stack.Iterator()
	it.Begin()
	for it.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

Queue is a FIFO data structure.

Implements Container interface.

drawing

type Queue interface {
	Put(value interface{})
	Get() (interface{}, error)

	container.Container
	// Empty() bool
	// Size() int
	// Clear()
	// Values() []interface{}
}

LinkedListQueue

LinkedListQueue is a stack based on SinglyLinkedList.

Implements Queue, ValueIterator and IndexIterator interface.

package main

import (
	"fmt"

	"github.com/prprprus/ds/queue/linkedlistqueue"
)

func main() {
	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]

	// iterator
	it := queue.Iterator()
	it.Begin()
	for it.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

ArrayQueue is a stack based on ArrayList.

Implements Queue, ValueIterator and IndexIterator interface.

package main

import (
	"fmt"

	"github.com/prprprus/ds/queue/arrayqueue"
)

func main() {
	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]

	// iterator
	it := queue.Iterator()
	it.Begin()
	for it.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

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.

drawing

package main

import (
	"fmt"

	"github.com/prprprus/ds/skiplist"
	"github.com/prprprus/ds/util"
)

func main() {
	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"}]

	// iterator
	it := skiplist.Iterator()
	it.Begin()
	for it.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

Map stores key-value pairs with excellent operational performance. It should be noted that the keys must be comparable types.

Implements Container interface.

type Map interface {
	Put(key, value interface{})
	Get(key interface{}) (interface{}, error)
	Remove(key interface{})

	container.Container
	// Empty() bool
	// Size() int
	// Clear()
	// Values() []interface{}
}

HashMap

HashMap is a map based on hash table.

Implements Map interface.

drawing

package main

import (
	"github.com/prprprus/ds/maps/hashmap"
)

func main() {
	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

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"
)

func main() {
	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"}]

	// iterator
	it := m.Iterator()
	it.Begin()
	for it.Next() {
		fmt.Println(it.Key(), it.Value())
	}
	// output:
	// 1 a
	// 2 b
	// 3 c
	// 4 d
	it.End()
	for it.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

SkipMap is a map based on SkipList.

Implements Map, ValueIterator and KeyIterator.

package main

import (
	"fmt"

	"github.com/prprprus/ds/maps/linkedhashmap"
)

func main() {
	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"}]

	// iterator
	it := m.Iterator()
	it.Begin()
	for it.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

Set is used to store non-repeating values, usually with good operational performance.

Implements Container interface.

type Set interface {
	Add(values ...interface{})
	Remove(values ...interface{}) error
	Contains(values ...interface{}) bool

	container.Container
	// Empty() bool
	// Size() int
	// Clear()
	// Values() []interface{}
}

HashSet

HashSet is a set based on hash table.

Implements Set interface.

package main

import (
	"github.com/prprprus/ds/set/hashset"
)

func main() {
	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

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"
)

func main() {
	s := linkedhashset.New() // []
	s.Add(1)                 // [1]
	s.Add(2)                 // [1 2]
	s.Add(3)                 // [1 2 3]

	// iterator
	it := s.Iterator()
	it.Begin()
	for it.Next() {
		fmt.Println(it.Value())
	}
	// output:
	// 1
	// 2
	// 3
	it.End()
	for it.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

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"
)

func main() {
	s := skipset.New(util.IntComparator) // []
	s.Add(1)                             // [1]
	s.Add(2)                             // [1 2]
	s.Add(3)                             // [1 2 3]

	// iterator
	it := s.Iterator()
	it.Begin()
	for it.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()               // []
}

Util

Contains some helper functions.

Comparator

Comparator provides the following built-in type of comparator.

func IntComparator(a, b interface{}) int

func Int8Comparator(a, b interface{}) int

func Int16Comparator(a, b interface{}) int

func Int32Comparator(a, b interface{}) int

func Int64Comparator(a, b interface{}) int

func UIntComparator(a, b interface{}) int

func UInt8Comparator(a, b interface{}) int

func UInt16Comparator(a, b interface{}) int

func UInt32Comparator(a, b interface{}) int

func UInt64Comparator(a, b interface{}) int

func Float32Comparator(a, b interface{}) int

func Float64Comparator(a, b interface{}) int

func ByteComparator(a, b interface{}) int

func RuneComparator(a, b interface{}) int

func StringComparator(a, b interface{}) int

The 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"
)

type People struct {
    name string
    age  int
}

func AgeComparator(a, b interface{}) int {
    c1 := a.(People)
    c2 := b.(People)
    switch {
	case c1.age < c2.age:
		return -1
	case c1.age > c2.age:
		return 1
	default:
		return 0
	}
}

func main() {
    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}]
}

Benchmarking

go test -run=NO_TEST -bench=. -benchmem -benchtime 1s github.com/prprprus/ds/...

ds-bench-1.png ds-bench-2.png ds-bench-3.png ds-bench-4.png ds-bench-5.png ds-bench-6.png

Releases

No releases published

Packages

No packages published

Languages