GoSTL

GoSTL是一个go语言数据结构和算法库,类似C++的STL,但功能更强大。结合go语言的特点,大部分数据结构都实现了线程安全,可以在创建对象的时候通过配置参数指定是否开启。

功能列表

  • 数据结构

    • 切片(slice)
    • 数组(array)
    • 向量(vector)
    • 列表(list)
    • 双端队列(deque)
    • 队列(queue)
    • 优先队列(priority_queue)
    • 栈(stack)
    • 红黑树(rbtree)
    • 映射(map/multimap)
    • 集合(set/multiset)
    • 位映射(bitmap)
    • 布隆过滤器(bloom_filter)
    • 哈希映射树(hamt)
    • 一致性哈希(ketama)
    • 跳表(skiplist)
  • 算法

    • 快排(sort)
    • 稳定排序(stable_sort)
    • 二分查找(binary_search)
    • 二分查找第一个元素的位置(lower_bound)
    • 二分查找第一个大于该元素的位置(upper_bound)
    • 下一个排列组合(next_permutation)

例子

切片(slice)

这个库中的切片是对go原生切片的重定义。
下面是一个如何将go原生的切片转成IntSlice,然后对其排序的例子。

package mainimport (   "fmt"   "github.com/liyue201/gostl/algorithm/sort"   "github.com/liyue201/gostl/ds/slice"   "github.com/liyue201/gostl/utils/comparator")func main() {   a := slice.IntSlice(make([]int, 0))   a = append(a, 2)   a = append(a, 1)   a = append(a, 3)   fmt.Printf("%v\n", a)      // sort in ascending   sort.Sort(a.Begin(), a.End())   fmt.Printf("%v\n", a)      // sort in descending   sort.Sort(a.Begin(), a.End(), comparator.Reverse(comparator.BuiltinTypeComparator))   fmt.Printf("%v\n", a)}

数组(array)

数组是一种一旦创建长度就固定的数据结构,支持随机访问和迭代器访问。

package mainimport (    "fmt"    "github.com/liyue201/gostl/ds/array")func main() {    a := array.New(5)    for i := 0; i < a.Size(); i++ {        a.Set(i, i + 1)    }    for i := 0; i < a.Size(); i++ {        fmt.Printf("%v ", a.At(i))    }    fmt.Printf("\n")    for iter := a.Begin(); iter.IsValid(); iter.Next() {        fmt.Printf("%v ", iter.Value())    }}

vector

向量是一种大小可以自动伸缩的数据结构,内部使用切片实现。支持随机访问和迭代器访问。

package mainimport (    "fmt"    "github.com/liyue201/gostl/algorithm/sort"    "github.com/liyue201/gostl/ds/vector"    "github.com/liyue201/gostl/utils/comparator")func main() {    v := vector.New()    v.PushBack(1)    v.PushBack(2)    v.PushBack(3)    for i := 0; i < v.Size(); i++ {        fmt.Printf("%v ", v.At(i))    }    fmt.Printf("\n")    // sort in descending    sort.Sort(v.Begin(), v.End(), comparator.Reverse(comparator.BuiltinTypeComparator))    for iter := v.Begin(); iter.IsValid(); iter.Next() {        fmt.Printf("%v ", iter.Value())    }}

列表(list)

  • 简单列表

简单列表是一种单向列表,支持从头部和尾部插入数据,只支持从头部遍历数据。

package mainimport (    "fmt"    "github.com/liyue201/gostl/ds/list/simple_list")func main() {    l := simple_list.New()    l.PushBack(1)    l.PushFront(2)    l.PushFront(3)    l.PushBack(4)    for n := l.FrontNode(); n != nil; n = n.Next() {        fmt.Printf("%v ", n.Value)    }}
  • 双向列表

双向列表,支持从头部和尾部插入数据,支持从头部和尾部遍历数据。

package mainimport (    "fmt"    list "github.com/liyue201/gostl/ds/list/bid_list")func main() {    l := list.New()    l.PushBack(1)    l.PushFront(2)    l.PushFront(3)    l.PushBack(4)    for n := l.FrontNode(); n != nil; n = n.Next() {        fmt.Printf("%v ", n.Value)    }    fmt.Printf("\n", )    for n := l.BackNode(); n != nil; n = n.Prev() {        fmt.Printf("%v ", n.Value)    }}

双端队列(deque)

双端队列支持从头部和尾部高效的插入数据,支持随机访问和迭代器访问。

package mainimport (    "fmt"    "github.com/liyue201/gostl/algorithm/sort"    "github.com/liyue201/gostl/ds/deque")func main() {    q := deque.New()    q.PushBack(2)    q.PushFront(1)    q.PushBack(3)    q.PushFront(4)    fmt.Printf("%v\n", q)    sort.Sort(q.Begin(), q.End())    fmt.Printf("%v\n", q)    fmt.Printf("%v\n", q.PopBack())    fmt.Printf("%v\n", q.PopFront())    fmt.Printf("%v\n", q)}

队列(queue)

队列是一种先进先出的数据结构,底层使用双端队列或者链表作为容器,默认使用双端队列,若想使用链表,可以在创建对象时使用queue.WithListContainer()参数。支持线程安全。

package mainimport (    "fmt"    "github.com/liyue201/gostl/ds/queue"    "sync"    "time")func example1()  {    fmt.Printf("example1:\n")    q := queue.New()    for i := 0; i < 5; i++ {        q.Push(i)    }    for !q.Empty() {        fmt.Printf("%v\n", q.Pop())    }}//  基于链表func example2()  {    fmt.Printf("example2:\n")    q := queue.New(queue.WithListContainer())    for i := 0; i < 5; i++ {        q.Push(i)    }    for !q.Empty() {        fmt.Printf("%v\n", q.Pop())    }}// 线程安全func example3() {    fmt.Printf("example3:\n")    s := queue.New(queue.WithThreadSave())    sw := sync.WaitGroup{}    sw.Add(2)    go func() {        defer sw.Done()        for i := 0; i < 10; i++ {            s.Push(i)            time.Sleep(time.Microsecond * 100)        }    }()    go func() {        defer sw.Done()        for i := 0; i < 10; {            if !s.Empty() {                val := s.Pop()                fmt.Printf("%v\n", val)                i++            } else {                time.Sleep(time.Microsecond * 100)            }        }    }()    sw.Wait()}func main() {    example1()    example2()    example3()}

优先队列(priority_queue)

优先队列基于go标准库的container/heap包实现,支持线程安全。

package mainimport (    "fmt"    "github.com/liyue201/gostl/ds/priority_queue"    "github.com/liyue201/gostl/utils/comparator")func main() {    q := priority_queue.New(priority_queue.WithComparator(comparator.Reverse(comparator.BuiltinTypeComparator)),        priority_queue.WithThreadSave())    q.Push(5)    q.Push(13)    q.Push(7)    q.Push(9)    q.Push(0)    q.Push(88)    for !q.Empty() {        fmt.Printf("%v\n", q.Pop())    }}

栈(stack)

栈是一种后进先出的数据结构,底层使用双端队列或者链表作为容器,默认使用双端队列,若想使用链表,可以在创建对象时使用queue.WithListContainer()参数。支持线程安全。

package mainimport (    "fmt"    "github.com/liyue201/gostl/ds/stack"    "sync"    "time")func example1() {    fmt.Printf("example1:\n")    s := stack.New()    s.Push(1)    s.Push(2)    s.Push(3)    for !s.Empty() {        fmt.Printf("%v\n", s.Pop())    }}// based on listfunc example2() {    fmt.Printf("example2:\n")    s := stack.New(stack.WithListContainer())    s.Push(1)    s.Push(2)    s.Push(3)    for !s.Empty() {        fmt.Printf("%v\n", s.Pop())    }}// thread-savefunc example3() {    fmt.Printf("example3:\n")    s := stack.New(stack.WithThreadSave())    sw := sync.WaitGroup{}    sw.Add(2)    go func() {        defer sw.Done()        for i := 0; i < 10; i++ {            s.Push(i)            time.Sleep(time.Microsecond * 100)        }    }()    go func() {        defer sw.Done()        for i := 0; i < 10; {            if !s.Empty() {                val := s.Pop()                fmt.Printf("%v\n", val)                i++            } else {                time.Sleep(time.Microsecond * 100)            }        }    }()    sw.Wait()}func main() {    example1()    example2()    example3()}

红黑树(rbtree)

红黑树是一种平衡二叉排序树,用于高效的插入和查找数据。

package mainimport (    "fmt"    "github.com/liyue201/gostl/ds/rbtree")func main()  {    tree := rbtree.New()    tree.Insert(1, "aaa")    tree.Insert(5, "bbb")    tree.Insert(3, "ccc")    fmt.Printf("find %v returns %v\n",5, tree.Find(5))    tree.Traversal(func(key, value interface{}) bool {        fmt.Printf("%v : %v\n", key, value)        return true    })    tree.Delete(tree.FindNode(3))}

映射(map)

映射底层使用红黑树实现,支持按key顺序迭代访问,有别于go原生的map类型(go原生的map底层是哈希,不支持按key顺序迭代访问)。支持线程安全。

package mainimport (    "fmt"    "github.com/liyue201/gostl/ds/map")func main() {    m := treemap.New(treemap.WithThreadSave())    m.Insert("a", "aaa")    m.Insert("b", "bbb")    fmt.Printf("a = %v\n", m.Get("a"))    fmt.Printf("b = %v\n", m.Get("b"))        m.Erase("b")}

集合(set)

集合底层使用红黑树实现,支持线程安全。支持集合的基本运算,如求并集,交集,差集。支持线程安全。

package mainimport (    "fmt"    "github.com/liyue201/gostl/ds/set")func main()  {    s := set.New(set.WithThreadSave())    s.Insert(1)    s.Insert(5)    s.Insert(3)    s.Insert(4)    s.Insert(2)    s.Erase(4)    for iter := s.Begin(); iter.IsValid(); iter.Next() {        fmt.Printf("%v\n", iter.Value())    }    fmt.Printf("%v\n", s.Contains(3))    fmt.Printf("%v\n", s.Contains(10))}

位映射(bitmap)

位映射用于快速标记和查找一个非负整数是否集合中。相对于map或数组占用内存空间更小。

package mainimport (    "fmt"    "github.com/liyue201/gostl/ds/bitmap")func main() {    bm := bitmap.New(1000)    bm.Set(6)    bm.Set(10)    fmt.Printf("%v\n", bm.IsSet(5))    fmt.Printf("%v\n", bm.IsSet(6))    bm.Unset(6)    fmt.Printf("%v\n", bm.IsSet(6))}

布隆过滤器(bloom_filter)

布隆过滤器用来快速判断数据是否在集合中,底层使用bitmap实现,相对于map占用内存空间更小。缺点是不支持删除和有一定的错误率。支持线程安全。支持数据导出和通过导出的数据重现构建。

package mainimport (    "fmt"    "github.com/liyue201/gostl/ds/bloomfilter")func main() {    filter := bloom.New(100, 4, bloom.WithThreadSave())    filter.Add("hhhh")    filter.Add("gggg")    fmt.Printf("%v\n", filter.Contains("aaaa"))    fmt.Printf("%v\n", filter.Contains("gggg"))}

哈希映射树(hamt)

哈希映射树相对于传统哈希(开放地址法或链表法哈希),出现哈希冲突的概率更小,空间利用率更高。扩容缩容性时间复杂度低。支持线程安全。

package mainimport (    "fmt"    "github.com/liyue201/gostl/ds/hamt")func main() {    h := hamt.New()    // h := hamt.New(hamt.WithThreadSave())    key := []byte("aaaaa")    val := "bbbbbbbbbbbbb"    h.Insert(key, val)    fmt.Printf("%v = %v\n", string(key), h.Get(key))    h.Erase(key)    fmt.Printf("%v = %v\n", string(key), h.Get(key))}

一致性哈希(ketama)

一致性哈希ketama算法,使用64位的哈希函数和map存储,出现冲突的概率更小。支持线程安全。

package mainimport (    "github.com/liyue201/gostl/ds/ketama"    "fmt")func main() {    k := ketama.New()    k.Add("1.2.3.3")    k.Add("2.4.5.6")    k.Add("5.5.5.1")    node, _ := k.Get("aaa")    fmt.Printf("%v\n", node)    k.Remove("2.4.5.6")}

跳表(skliplist)

跳表是一种通过以空间换时间来实现快速查找的数据结构。支持线程安全。

package mainimport (    "fmt"    "github.com/liyue201/gostl/ds/skiplist")func main()  {    list := skiplist.New(skiplist.WithMaxLevel(15))    list.Insert("aaa", "1111")    list.Insert("bbb", "2222")    fmt.Printf("aaa = %v\n", list.Get("aaa"))    fmt.Printf("aaa = %v\n\n", list.Get("bbb"))    list.Traversal(func(key, value interface{}) bool {        fmt.Printf("key:%v value:%v\n", key, value)        return true    })    list.Remove("aaa")}

排序、稳定排序、二分查找

Sort: 内部使用的是快速排序算法。
Stable: 稳定排序,内部使用归并排序。
BinarySearch: 通过二分查找,判断一个元素是否在迭代器范围中。
LowerBound: 通过二分查找,找到第一个等于该元素的数据返回该迭代器。
UpperBound: 通过二分查找,找到第一个大于该元素的数据返回该迭代器。

package mainimport (    "github.com/liyue201/gostl/algorithm/sort"    "github.com/liyue201/gostl/utils/comparator"    "github.com/liyue201/gostl/ds/slice"    "fmt")func main()  {    a := make([]string, 0)    a = append(a, "bbbb")    a = append(a, "ccc")    a = append(a, "aaaa")    a = append(a, "bbbb")    a = append(a, "bb")    sliceA := slice.StringSlice(a)    ////Sort in ascending order    sort.Sort(sliceA.Begin(), sliceA.End())    //sort.Stable(sliceA.Begin(), sliceA.End())    fmt.Printf("%v\n", a)    if sort.BinarySearch(sliceA.Begin(), sliceA.End(), "bbbb") {        fmt.Printf("BinarySearch: found bbbb\n")    }    iter := sort.LowerBound(sliceA.Begin(), sliceA.End(), "bbbb")    if iter.IsValid() {        fmt.Printf("LowerBound bbbb: %v\n", iter.Value())    }    iter = sort.UpperBound(sliceA.Begin(), sliceA.End(), "bbbb")    if iter.IsValid() {        fmt.Printf("UpperBound bbbb: %v\n", iter.Value())    }    //Sort in descending order    sort.Sort(sliceA.Begin(), sliceA.End(), comparator.Reverse(comparator.BuiltinTypeComparator))    //sort.Stable(sliceA.Begin(), sliceA.End(), comparator.Reverse(comparator.BuiltinTypeComparator))    fmt.Printf("%v\n", a)}

下个排序组合(next_permutation)

这个函数修改迭代器范围内的数据为下一个排序组合。

package mainimport (    "github.com/liyue201/gostl/algorithm/sort"    "github.com/liyue201/gostl/ds/slice"    "github.com/liyue201/gostl/utils/comparator"    "fmt")func main()  {    a := slice.IntSlice(make([]int, 0))    for i := 1; i <= 3; i++ {        a = append(a, i)    }    fmt.Println("NextPermutation")    for {        fmt.Printf("%v\n", a)        if !sort.NextPermutation(a.Begin(), a.End()) {            break        }    }    fmt.Println("PrePermutation")    for {        fmt.Printf("%v\n", a)        if !sort.NextPermutation(a.Begin(), a.End(), comparator.Reverse(comparator.BuiltinTypeComparator)) {            break        }    }}