{"id":20285440,"url":"https://github.com/mramshaw/radix-trie","last_synced_at":"2026-07-03T21:03:56.091Z","repository":{"id":57587651,"uuid":"127546407","full_name":"mramshaw/radix-trie","owner":"mramshaw","description":"A radix (or possibly Patricia) trie","archived":false,"fork":false,"pushed_at":"2020-03-06T17:16:33.000Z","size":20,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-04T03:44:35.587Z","etag":null,"topics":["data-structures","go","golang","patricia-trie","radix","radix-trie","table-driven-testing","trie"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mramshaw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-31T15:45:12.000Z","updated_at":"2024-10-09T11:40:52.000Z","dependencies_parsed_at":"2022-09-12T21:10:34.586Z","dependency_job_id":null,"html_url":"https://github.com/mramshaw/radix-trie","commit_stats":null,"previous_names":["mramshaw/radix-tree"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/mramshaw/radix-trie","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mramshaw%2Fradix-trie","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mramshaw%2Fradix-trie/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mramshaw%2Fradix-trie/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mramshaw%2Fradix-trie/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mramshaw","download_url":"https://codeload.github.com/mramshaw/radix-trie/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mramshaw%2Fradix-trie/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278712717,"owners_count":26032742,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-07T02:00:06.786Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data-structures","go","golang","patricia-trie","radix","radix-trie","table-driven-testing","trie"],"created_at":"2024-11-14T14:26:42.776Z","updated_at":"2025-10-07T03:04:38.810Z","avatar_url":"https://github.com/mramshaw.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Radix Trie\n\n[![Build status](https://travis-ci.org/mramshaw/radix-trie.svg?branch=master)](https://travis-ci.org/mramshaw/radix-trie)\n[![Coverage Status](http://codecov.io/github/mramshaw/radix-trie/coverage.svg?branch=master)](http://codecov.io/github/mramshaw/radix-trie?branch=master)\n[![Go Report Card](https://goreportcard.com/badge/github.com/mramshaw/radix-trie?style=flat-square)](https://goreportcard.com/report/github.com/mramshaw/radix-trie)\n[![GoDoc](https://godoc.org/github.com/mramshaw/radix-trie?status.svg)](https://godoc.org/github.com/mramshaw/radix-trie)\n[![GitHub release](https://img.shields.io/github/v/release/mramshaw/radix-trie?style=flat-square)](https://github.com/mramshaw/radix-trie/releases)\n\nThis is mainly based on the [Wikipedia article](https://en.wikipedia.org/wiki/Radix_tree).\n\nNote that a __radix tree__ is a space-optimized [trie](https://en.wikipedia.org/wiki/Trie).\n\nAccording to the article cited above, tries were first suggested in 1959 by a Frenchman\nnamed René de la Briandais (`tri` is French for `sort`). According to Donald Knuth’s\nresearch in The Art of Computer Programming:\n\n\u003e Trie memory for computer searching was first recommended by René de la Briandais.\n\u003e He pointed out that we can save memory space at the expense of running time if we\n\u003e use a linked list for each node vector, since most of the entries in the vectors\n\u003e tend to be empty.\n\n[Note that this is not the approach being followed here.]\n\nMore particularly, this seems to be a __Patricia trie__ - which I believe is the binary form.\n\n![Patricia_trie](https://upload.wikimedia.org/wikipedia/commons/a/ae/Patricia_trie.svg)\n\nUPDATE: I found this example (also from Wikipedia) that shows an interesting edge case:\n\n![Edge_case](https://upload.wikimedia.org/wikipedia/commons/6/63/An_example_of_how_to_find_a_string_in_a_Patricia_trie.png)\n\nIt shows that __slow__ can be both a node - and a leaf - at the same time. This is something\nwhich I had not considered (another example might be __real__ and __realistic__). Interestingly,\nmy understanding was that the root node of the trie (it may - or may not - be true that trie\ncomes from _retrieval_) is always a single character whereas this diagram shows the root node\nas the entire word `slow`.\n\nFor retrieval purposes I am inclined to persist with using a single character as a root.\nThe only uses for a trie that I have been able to find are spell-checking and autocomplete\nfor search bars and the like. So being able to respond quickly to that first typed character\nsounds like what I am after. In the case of __bytes__ this would make it possible to use\nthe initial byte as an offset index, although I doubt this would be practical for runes.\n\n## Motivation\n\nI've been doing a lot of high-level programming lately (RESTful APIs, Scala/Akka) so\nsomething a little more low-level sounded like a nice change of pace. And it has also\nallowed me to investigate parts of __Go__ that I do not normally run into.\n\nMore importantly, it's a nice opportunity to use\n[Table-driven testing](https://dave.cheney.net/2013/06/09/writing-table-driven-tests-in-go).\n\n## Prerequisites\n\n1. A recent version of Go\n\n2. `make` installed\n\n[Or can simply type `go test -v`.]\n\n## Expected Usage\n\nFirst seven inserts:\n\n```\n  1 (romane) 2 (romanus) 3 (romulus)   4 (rubens)   5 (ruber)         6 (rubicon)        7 (rubicundus)\n  |          |           |             |            |                 |                  |\n  r          r           r             r            r                 r                  r\n  |          |           |            / \\          / \\               / \\                / \\\nomane       oman         om          om  ubens    om  \\             om  ub             om  ub\n            / \\         / \\         / \\          / \\   \\           / \\    \\           / \\    \\\n           e   us      an ulus    an  ulus     an  ulus \\        an  ulus  *        an  ulus  *\n                      /  \\       /  \\         /  \\      ube     /  \\      / \\      /  \\      / \\\n                     e    us    e    us      e    us   /   \\   e    us   e  icon  e    us   e   \\\n                                                      ns    r           / \\                / \\   \\\n                                                                       ns  r              ns  r  ic\n                                                                                                /  \\\n                                                                                              on  undus\n```\n\n## To Run\n\nType the following command:\n\n    $ make\n\nThe results should look as follows:\n\n    GOPATH=/go GOOS=linux GOARCH=amd64 gofmt -d -e -s -w *.go\n    GOPATH=/go GOOS=linux GOARCH=amd64 golint -set_exit_status *.go\n    GOPATH=/go GOOS=linux GOARCH=amd64 go tool vet *.go\n    GOPATH=/go GOOS=linux GOARCH=amd64 go test -v\n    === RUN   TestInsert\n    --- PASS: TestInsert (0.00s)\n    === RUN   TestFind\n    --- PASS: TestFind (0.00s)\n    PASS\n    ok\n\n## Table-driven Tests\n\nIn concept, these sounded like a great idea. In practice, I'd have to say my feelings are mixed.\n\nLike all tests, they get unwieldy very quickly.\n\n[For an example of how tests can become opaque very quickly, check out the\n[following example](https://github.com/mramshaw/RESTful-Recipes/blob/master/src/test/main_test.go).\nWhile I made every effort to code these tests to be as transparent as possible, I do not think\nthe results - in terms of being able to `grok` what I am actually testing __for__ - are all that\neasy to sort out. Doing so requires scrolling through pages of tests in order to form an overview.]\n\nOn the other hand, the table-driven test framework allowed me to code up the __Find__ tests - and\nmock up some data to test them with - while I was still working on the __Insert__ tests, whereas\npreviously I would have had to complete the __Insert__ tests (and code) in order to test the matching\n__Find__ tests (and code). Or maybe do them both in lock-step, step-wise.\n\nAs it is, being able to do them both at the same time has been a great help, at least conceptually.\n\nLooking at examples of this testing style, it seemed like it would be possible to quickly grasp - at\na high level - what the tests ***were***. But my experience - in practice - is that this framework\nstill gets very cluttered quite quickly, so that this high-level overview is not really possible.\n\nI still think this approach is great - but I'd probably reserve it for lower-level components, rather\nthan for system testing.\n\nUPDATE: One nice feature of Table-driven Tests is that they are very easily extended. For instance,\nit can be trivially simple to add a new edge case (such as the empty string - \"\" - for example) with\na few new lines of code (it may not always be this simple, but it's easy to think of these types of\nexamples where extending a table-driven test for a new edge case is far easier than having to write\nan entirely new test). More tests is almost always better than less, so being able to add edge cases\nin a very simple way seems like a good approach to encourage more and better testing.\n\n## To Do\n\n- [ ] Investigate applications of Patricia tries\n- [x] Refactor tests to avoid some of the duplicated code\n- [x] Add code and tests to allow for entries such as \"slow\", \"slower\", \"slowly\"\n- [x] Find out the idiom for stacking __Insert__ and __Find__ tests (avoiding mocks)\n- [ ] Investigate whether byte-based __and__ rune-based options are viable\n- [ ] Find more examples of tries in use - specifically Rune-based CJKV (Chinese, Japanese, Korean, Vietnamese)\n- [x] Add example of Chinese Rune-based trie\n- [ ] Find out whether the usual practice is to sort trie entries (the Wikipedia example __is__ sorted)\n- [ ] Tests and code for 'retrieve all entries' functionality\n- [x] Upgrade to latest release of Golang (1.14 as of the time of writing)\n- [x] Upgrade `release` badge to confomr to new Shields.io standards\n\n## Credits\n\nThis follows on from work four of us did as a group in a couple of hours at the local Golang Meetup.\n\nIn particular, Dan coded up the original __Table-driven Tests__, which proved very instructive.\n\nBlake coded up the original ASCII art, which has been fun to elaborate on.\n\nMy original fork of this project may be seen here:\n\n    https://github.com/mramshaw/golangvan/tree/master/radix-trie\n\nAs I have departed heavily from the original framework (both __design__ and __implementation__) I created this repo.\n\nIn particular, I have followed a __Rune__-based approach, rather than a __Byte__-based approach. I have opted\nfor lazy structures, which are cheaper in terms of memory requirements but possibly costly in performance terms.\nAlso, the original goal was to be as efficient as possible, whereas I am not greatly concerned with efficiency\nhere. My goal is an __MVP__ (minimum viable product; meaning a proof-of-concept, demo or spike) for learning purposes.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmramshaw%2Fradix-trie","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmramshaw%2Fradix-trie","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmramshaw%2Fradix-trie/lists"}