Golang implementation of Radix trees

go-radix Build Status

Provides the radix package that implements a radix tree. The package only provides a single Tree implementation, optimized for sparse nodes.

As a radix tree, it provides the following:

  • O(k) operations. In many cases, this can be faster than a hash table since the hash function is an O(k) operation, and hash tables have very poor cache locality.
  • Minimum / Maximum value lookups
  • Ordered iteration

For an immutable variant, see go-immutable-radix.

Documentation

The full documentation is available on Godoc.

Example

Below is a simple example of usage

// Create a tree
r := radix.New()
r.Insert("foo", 1)
r.Insert("bar", 2)
r.Insert("foobar", 2)

// Find the longest prefix match
m, _, _ := r.LongestPrefix("foozip")
if m != "foo" {
    panic("should be foo")
}
Comments
  • Allow calling Delete() inside Walk() and WalkPrefix()

    Allow calling Delete() inside Walk() and WalkPrefix()

    Closes #14 Closes #12

    In recursiveWalk called by Walk and WalkPrefix, we were iterating over the edges of a node. The edges as well as the current node object itself (when mergeChild is called) can be modified by calls to Delete.

    This commit modifies the loop to handle modifications correctly and prevent a nil pointer dereference panic in the case detailed in TestWalkDelete.

  • Fix panic when node is deleted while walking

    Fix panic when node is deleted while walking

    carries https://github.com/armon/go-radix/pull/12 closes https://github.com/armon/go-radix/pull/12

    relates to https://github.com/moby/libnetwork/pull/2581

  • refactor: Change replaceEdge func to updateEdge

    refactor: Change replaceEdge func to updateEdge

    The purpose of replaceEdge func is to redirect current edge to a new node with common prefix.

    So pass label and node directly instead of creating a new edge structure.

  • Speed up Insert

    Speed up Insert

    Rewrite addEdge to use binary search to insert the element in the already sorted slice.

    Benchmark for Insert:

    name       old time/op    new time/op    delta
    Insert-16     624ns ± 4%     523ns ± 3%  -16.29%  (p=0.029 n=4+4)
    
    name       old alloc/op   new alloc/op   delta
    Insert-16      169B ± 0%      137B ± 0%  -18.93%  (p=0.029 n=4+4)
    
    name       old allocs/op  new allocs/op  delta
    Insert-16      4.00 ± 0%      3.00 ± 0%  -25.00%  (p=0.029 n=4+4)
    

    Closes #15

  • Insert can be 25% faster, using 28% fewer allocations

    Insert can be 25% faster, using 28% fewer allocations

    Sorry for the drive by. This is a useful package and I've made extensive changes to my version. There is an easy performance improvement. If you like it, you can take it, no attribution necessary. If not, feel free to close with no further comment.

    The numbers I quoted in the header are for benchmarks when 10,000 entries are added to a tree. The order of insertions doesn't matter. They can be ordered, unordered, and even reverse ordered. Always 28% fewer allocations occur.

    The package requires the edges are kept sorted. Currently the addEdge method performs a full sort after appending the new edge. Using the same binary search other parts of the package use, the insertion point can be found exactly. The binary search is much more efficient than the sort.

    Replace

    func (n *node) addEdge(e edge) {
    	n.edges = append(n.edges, e)
    	n.edges.Sort()
    }
    

    with

    func (n *node) addEdge(e edge) {
    	num := len(n.edges)
    	idx := sort.Search(num, func(i int) bool {
    		return n.edges[i].label >= e.label
    	})
    
    	n.edges = append(n.edges, edge{})
    	copy(n.edges[idx+1:], n.edges[idx:])
    	n.edges[idx] = e
    }
    
  • Fix panic when node is deleted while walking

    Fix panic when node is deleted while walking

    If a node is deleted from within the walk function, currently the recursive walk will panic if it then tries to go down that branch. Instead, terminate walking that branch.

  • Queryable Sub-trees?

    Queryable Sub-trees?

    I see that the implementation is recursive, but this isn't exposed in the public API. For example it would be powerful to get a reference to a sub-tree and then to be able to query it the same as the root tree.

    I don't have the time to deep dive into the implementation, so I was hoping you could answer this for me: Is there any technical reason why non-root Nodes can't be exposed and queried like the root Node? Is there some quirk in the implementation that prevents this, that requires all queries to be made from the root?

  • gofmt

    gofmt

    Just ran

    gofmt -w .
    

    on the project root. That's all.

    https://blog.golang.org/go-fmt-your-code


    I made this PR with a project going on over at https://github.com/rotblauer/gofmt-att, and it's definitely a work in progress. So if I got something wrong, or this is annoying at all, please file an issue over there and we'll sort it out.

  • [Question] Router any paths

    [Question] Router any paths

    Hi,

    Before anything, great package :+1:

    I'm creating an personal web framework and I need to route my routes :smile:. I'm studying and find a possible solution, use radix tree, and found this package.

    But I've a problem, how to route the path if I catch a path with parameters ?

    Ex.:

    
    package main
    
    import (
    	"fmt"
    
    	radix "github.com/armon/go-radix"
    )
    
    func main() {
    
    	r := radix.New()
    
    	r.Insert("/a/b/c/:d", 1)
    	r.Insert("/a/b/n/:d", 2)
    	r.Insert("/a/t/u/:i", 2)
    
    	m, _, _ := r.LongestPrefix("/a/b/c/test")
    
    	fmt.Println(m) // Don't match path
    
    }
    
    

    In this scene this code not match my path, but should. Can you help me, it is possible to do?

    Tks

  • Handle more edge cases for Delete()

    Handle more edge cases for Delete()

    We should never merge into the root node since it's assumed to be the empty string.

    We need to check for deleting this node from the parent before we have potentially merged the node and its child. If we check after we've merged, it might be the case that the merged node has no children (in which case we don't want to delete it from the parent, since it's still a valid entry.)

    This patch includes tests to check that we're handling these cases.

  • Added support for Linux on power

    Added support for Linux on power

    Hi, I had added ppc64le(Linux on Power) support on travis-ci in the branch and looks like its been successfully added. I believe it is ready for the final review and merge. The travis ci build logs can be verified from the link below.

    https://travis-ci.com/github/ujjwalsh/go-radix/builds/188880895 Please have a look.

    Regards, ujjwal

Adaptive Radix Trees implemented in Go

An Adaptive Radix Tree Implementation in Go This library provides a Go implementation of the Adaptive Radix Tree (ART). Features: Lookup performance s

Dec 30, 2022
A generic Go library for implementations of tries (radix trees), state commitments and proofs of inclusion

trie.go Go library for implementations of tries (radix trees), state commitments and proof of inclusion for large data sets. It implements a generic 2

Aug 3, 2022
An immutable radix tree implementation in Golang

go-immutable-radix Provides the iradix package that implements an immutable radix tree. The package only provides a single Tree implementation, optimi

Dec 29, 2022
A radix sorting library for Go (golang)

zermelo A radix sorting library for Go. Trade memory for speed! import "github.com/shawnsmithdev/zermelo" func foo(large []uint64) zermelo.Sort(l

Jul 30, 2022
A Left-Leaning Red-Black (LLRB) implementation of balanced binary search trees for Google Go

GoLLRB GoLLRB is a Left-Leaning Red-Black (LLRB) implementation of 2-3 balanced binary search trees in Go Language. Overview As of this writing and to

Dec 23, 2022
A go implementation of Verkle trees

go-verkle A very experimental implementation of Verkle trees. When production-ready, the code is to be split between go-kzg and go-ethereum. Notes Nod

Jan 8, 2023
Generic types that are missing from Go, including sets, trees, sorted lists, etc.

go-typ Generic types that are missing from Go, including sets, trees, sorted lists, etc. All code is implemented with 0 dependencies and in pure Go co

Dec 4, 2022
A simple Set data structure implementation in Go (Golang) using LinkedHashMap.

Set Set is a simple Set data structure implementation in Go (Golang) using LinkedHashMap. This library allow you to get a set of int64 or string witho

Sep 26, 2022
HyperLogLog and HyperLogLog++ implementation in Go/Golang.
HyperLogLog and HyperLogLog++ implementation in Go/Golang.

HyperLogLog and HyperLogLog++ Implements the HyperLogLog and HyperLogLog++ algorithms. HyperLogLog paper: http://algo.inria.fr/flajolet/Publications/F

Nov 24, 2022
Golang FrodoKEM implementation

FrodoKEM in Golang Golang implementation of FrodoKEM: a Practical quantum-secure key encapsulation from generic lattices (https://frodokem.org). This

Mar 3, 2022
Trie data structure implementation in Golang 🌳

Gotri Gotri is an Unicode character based Trie/prefix tree implementation in Go, with the suggestion/auto-complete feature for character searching. Si

Jun 17, 2022
Access LeetCode problems via id, Golang implementation

LCid-Go Introduction This naive toy is based on bunnyxt/lcid, and implemented in Golang for practice. They are same in program logic and static files.

Jan 15, 2022
Go-merkle - Merkle tree implementation in Golang

go-merkle go-merkle implements a simple merkle tree in Golang. It allows to obta

Aug 8, 2022
Go implementation of Count-Min-Log

Count-Min-Log Count-Min-Log sketch: Approximately counting with approximate counters - Guillaume Pitel & Geoffroy Fouquier TL;DR: Count-Min-Log Sketch

Jan 4, 2023
A Go implementation of the Elias-Fano encoding

go-ef A Go implementation of the Elias-Fano encoding Example package main import ( "fmt" "github.com/amallia/go-ef" "os" ) func main() {

Nov 23, 2022
Set is a useful collection but there is no built-in implementation in Go lang.

goset Set is a useful collection but there is no built-in implementation in Go lang. Why? The only one pkg which provides set operations now is golang

Sep 26, 2022
A skip list implementation in Go

About This is a library implementing skip lists for the Go programming language (http://golang.org/). Skip lists are a data structure that can be used

Sep 21, 2022
Go implementation of C++ STL iterators and algorithms.

iter Go implementation of C++ STL iterators and algorithms. Less hand-written loops, more expressive code. README translations: 简体中文 Motivation Althou

Dec 19, 2022