rbtree

package module
v0.0.0-...-22a0edf Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 27, 2018 License: Apache-2.0 Imports: 4 Imported by: 0

README

rbtree License GoDoc Go Report Card

A red-black tree with an API similar to C++ STL's.

a high performance red-black tree with less heap objects.

Installtion

    go get -u -v github.com/cdongyang/rbtree

Test

run test:

./test.sh
coverage: 95.5% of statements

run bench:

/bin/go test -v -benchmem -run=^$ github.com/cdongyang/rbtree -bench ^Benchmark$

Example

more example please see example_test.go

func ExampleMap() {
	var slice = []int{1, 4, 6, 5, 3, 7, 2, 9}
	// key type: int, value type: *int
	mp := rbtree.NewMap(int(0), new(int), func(a, b interface{}) int {
		return a.(int) - b.(int)
	})
	for i := range slice {
		mp.Insert(slice[i], &slice[i])
	}
	var indexOf = func(p *int) int {
		for i := range slice {
			if &slice[i] == p {
				return i
			}
		}
		return -1
	}
	// iterator
	for it, i := mp.Begin(), 0; it != mp.End(); it = it.Next() {
		fmt.Println(it.GetKey(), indexOf(it.GetVal().(*int)))
		i++
  }
  mp = nil // free tree to make it collect by GC
	//Output:
	//1 0
	//2 6
	//3 4
	//4 1
	//5 3
	//6 2
	//7 5
	//9 7
}

Types and functions

func NoescapeInterface(x interface{}) interface{}
type Map
    func NewMap(key, val interface{}, compare func(a, b interface{}) int) *Map
    func NewMultiMap(key, val interface{}, compare func(a, b interface{}) int) *Map
    func (s *Map) Begin() MapNode
    func (s *Map) Count(key interface{}) (count int)
    func (t *Map) Empty() bool
    func (s *Map) End() MapNode
    func (s *Map) EqualRange(key interface{}) (beg, end MapNode)
    func (s *Map) Erase(key interface{}) (count int)
    func (s *Map) EraseNode(n MapNode)
    func (s *Map) EraseNodeRange(beg, end MapNode) (count int)
    func (s *Map) Find(key interface{}) MapNode
    func (t *Map) GetMaxSpan() uint32
    func (s *Map) Init(unique bool, key, val interface{}, compare func(a, b interface{}) int)
    func (s *Map) Insert(key interface{}, val interface{}) (MapNode, bool)
    func (s *Map) LowerBound(key interface{}) MapNode
    func (t *Map) SetMaxSpan(maxSpan uint32)
    func (t *Map) Size() int
    func (t *Map) Unique() bool
    func (s *Map) UpperBound(key interface{}) MapNode
type MapNode
    func (n MapNode) GetData() (key, val interface{})
    func (n MapNode) GetKey() interface{}
    func (n MapNode) GetMap() *Map
    func (n MapNode) GetVal() interface{}
    func (n MapNode) Last() MapNode
    func (n MapNode) Next() MapNode
    func (n MapNode) SetVal(val interface{})
type Set
    func NewMultiSet(data interface{}, compare func(a, b interface{}) int) *Set
    func NewSet(data interface{}, compare func(a, b interface{}) int) *Set
    func (s *Set) Begin() SetNode
    func (s *Set) Count(data interface{}) (count int)
    func (t *Set) Empty() bool
    func (s *Set) End() SetNode
    func (s *Set) EqualRange(data interface{}) (beg, end SetNode)
    func (s *Set) Erase(data interface{}) (count int)
    func (s *Set) EraseNode(n SetNode)
    func (s *Set) EraseNodeRange(beg, end SetNode) (count int)
    func (s *Set) Find(data interface{}) SetNode
    func (t *Set) GetMaxSpan() uint32
    func (s *Set) Init(unique bool, data interface{}, compare func(a, b interface{}) int)
    func (s *Set) Insert(data interface{}) (SetNode, bool)
    func (s *Set) LowerBound(data interface{}) SetNode
    func (t *Set) SetMaxSpan(maxSpan uint32)
    func (t *Set) Size() int
    func (t *Set) Unique() bool
    func (s *Set) UpperBound(data interface{}) SetNode
type SetNode
    func (n SetNode) GetData() interface{}
    func (n SetNode) GetSet() *Set
    func (n SetNode) Last() SetNode
    func (n SetNode) Next() SetNode

Memory alloc

I use a slice of block memory to store node data. In addition, i store the unuse node in a two-dimension queue. when it needs a node, it pop from begin of queue, and push a node in queue when delete a node, so the node will reuse, cutting down the heap allocation. And each block memory can store curSpan nodes, however, the curSpan is dynamic change following the tree size. If curSpan < maxSpan, curSpan = 1 << (high bit of tree size), if curSpan > maxSpan, curSpan = maxSpan, so the number of heap objects will be close to O(tree size / maxSpan) when tree size if so large.

Attention

Because of the strategy of memory alloc, the data of interface{} return by method GetKey(),GetVal() or GetData() will store in block memory, so we should do the type assert immediately when get this kind of interface{}. If not, don't hold it for a long time, otherwise the block memory will not collect by GC until you never hold the interface{}.What's more, you should only read the interface{} in compare function.

Reference documentation

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrNotInTree  = errors.New("node is not a node of this tree")
	ErrNoLast     = errors.New("begin of tree has no Last()")
	ErrNoNext     = errors.New("end of tree has no Next()")
	ErrEraseEmpty = errors.New("can't erase empty node")
	ErrNoData     = errors.New("tree has no data")
	ErrNoValue    = errors.New("tree has no value")
	ErrBadKey     = errors.New("not same key type with tree")
	ErrBadValue   = errors.New("not same value type with tree")
)

Functions

func NoescapeInterface

func NoescapeInterface(x interface{}) interface{}

you can use this func to make the arguments of insert method don't escape to heap if it's not direct interface{} (make sure this)! you can find a example in file example_test.go. USE CAREFULLY!

Types

type Map

type Map struct {
	// contains filtered or unexported fields
}
Example
package main

import (
	"fmt"

	"github.com/cdongyang/rbtree"
)

func main() {
	var slice = []int{1, 4, 6, 5, 3, 7, 2, 9}
	// key type: int, value type: *int
	mp := rbtree.NewMap(int(0), new(int), func(a, b interface{}) int {
		return a.(int) - b.(int)
	})
	for i := range slice {
		mp.Insert(slice[i], &slice[i])
	}
	var indexOf = func(p *int) int {
		for i := range slice {
			if &slice[i] == p {
				return i
			}
		}
		return -1
	}
	// iterator
	for it, i := mp.Begin(), 0; it != mp.End(); it = it.Next() {
		fmt.Println(it.GetKey(), indexOf(it.GetVal().(*int)))
		i++
	}
	mp = nil // free tree to make it collect by GC
}
Output:

1 0
2 6
3 4
4 1
5 3
6 2
7 5
9 7

func NewMap

func NewMap(key, val interface{}, compare func(a, b interface{}) int) *Map

func NewMultiMap

func NewMultiMap(key, val interface{}, compare func(a, b interface{}) int) *Map

func (*Map) Begin

func (s *Map) Begin() MapNode

func (*Map) Count

func (s *Map) Count(key interface{}) (count int)

func (*Map) Empty

func (t *Map) Empty() bool

func (*Map) End

func (s *Map) End() MapNode

func (*Map) EqualRange

func (s *Map) EqualRange(key interface{}) (beg, end MapNode)

func (*Map) Erase

func (s *Map) Erase(key interface{}) (count int)

func (*Map) EraseNode

func (s *Map) EraseNode(n MapNode)

func (*Map) EraseNodeRange

func (s *Map) EraseNodeRange(beg, end MapNode) (count int)

func (*Map) Find

func (s *Map) Find(key interface{}) MapNode

func (*Map) GetMaxSpan

func (t *Map) GetMaxSpan() uint32

func (*Map) Init

func (s *Map) Init(unique bool, key, val interface{}, compare func(a, b interface{}) int)

func (*Map) Insert

func (s *Map) Insert(key interface{}, val interface{}) (MapNode, bool)

func (*Map) LowerBound

func (s *Map) LowerBound(key interface{}) MapNode

func (*Map) SetMaxSpan

func (t *Map) SetMaxSpan(maxSpan uint32)

func (*Map) Size

func (t *Map) Size() int

func (*Map) Unique

func (t *Map) Unique() bool

func (*Map) UpperBound

func (s *Map) UpperBound(key interface{}) MapNode

type MapNode

type MapNode struct {
	// contains filtered or unexported fields
}

MapNode is the iterator of Map, but it's not thread safe, if the node was erase from map, calling it's method may panic

func (MapNode) GetData

func (n MapNode) GetData() (key, val interface{})

func (MapNode) GetKey

func (n MapNode) GetKey() interface{}

GetKey get the key of MapNode, but you should not hold the return interface{}, instead, you should do type assert immediately when after call this method

func (MapNode) GetMap

func (n MapNode) GetMap() *Map

func (MapNode) GetVal

func (n MapNode) GetVal() interface{}

GetVal get the value of MapNode, but you should not hold the return interface{}, instead, you should do type assert immediately when after call this method

func (MapNode) Last

func (n MapNode) Last() MapNode

func (MapNode) Next

func (n MapNode) Next() MapNode

func (MapNode) SetVal

func (n MapNode) SetVal(val interface{})

type Set

type Set struct {
	// contains filtered or unexported fields
}

func NewMultiSet

func NewMultiSet(data interface{}, compare func(a, b interface{}) int) *Set

NewSet return a not unique set with data type and compare func, the return set has been executed init func.

func NewSet

func NewSet(data interface{}, compare func(a, b interface{}) int) *Set

NewSet return a unique set with data type and compare func, the return set has been executed init func.

func (*Set) Begin

func (s *Set) Begin() SetNode

Begin return the first SetNode of set, if set is empty, it return set.End()

func (*Set) Count

func (s *Set) Count(data interface{}) (count int)

func (*Set) Empty

func (t *Set) Empty() bool

func (*Set) End

func (s *Set) End() SetNode

End represent the end of set,but it isn't a real node

func (*Set) EqualRange

func (s *Set) EqualRange(data interface{}) (beg, end SetNode)

func (*Set) Erase

func (s *Set) Erase(data interface{}) (count int)

func (*Set) EraseNode

func (s *Set) EraseNode(n SetNode)

EraseNode erase a SetNode from tree, if SetNode has been erased, calling will panic

func (*Set) EraseNodeRange

func (s *Set) EraseNodeRange(beg, end SetNode) (count int)

func (*Set) Find

func (s *Set) Find(data interface{}) SetNode

func (*Set) GetMaxSpan

func (t *Set) GetMaxSpan() uint32

func (*Set) Init

func (s *Set) Init(unique bool, data interface{}, compare func(a, b interface{}) int)

Init init the set, function NewSet and NewMultiSet will calle it, only the first call of this function will have an affect on set

func (*Set) Insert

func (s *Set) Insert(data interface{}) (SetNode, bool)

func (*Set) LowerBound

func (s *Set) LowerBound(data interface{}) SetNode

func (*Set) SetMaxSpan

func (t *Set) SetMaxSpan(maxSpan uint32)

func (*Set) Size

func (t *Set) Size() int

func (*Set) Unique

func (t *Set) Unique() bool

func (*Set) UpperBound

func (s *Set) UpperBound(data interface{}) SetNode

type SetNode

type SetNode struct {
	// contains filtered or unexported fields
}

SetNode is the iterator of set, but it's not thread safe, if the node was erase from set, calling it's method may panic

func (SetNode) GetData

func (n SetNode) GetData() interface{}

GetData get the data of SetNode, but you should not hold the return interface{}, instead, you should do type assert immediately when after call this method

func (SetNode) GetSet

func (n SetNode) GetSet() *Set

GetSet return the Set that current node belong to.

func (SetNode) Last

func (n SetNode) Last() SetNode

Last return the last node of current node. it will panic if current node equal to set.Begin().

func (SetNode) Next

func (n SetNode) Next() SetNode

Next return the next node of current node. it will panic if current node equal to set.End().

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL