Skip to content

Commit fc8d961

Browse files
committed
add trie st
1 parent a66dda4 commit fc8d961

File tree

5 files changed

+335
-9
lines changed

5 files changed

+335
-9
lines changed

README.md

+2-9
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,11 @@ To test each algorithm(data structure), instead of running the file directly, yo
1919
## Index
2020

2121
* 1 FUNDAMENTALS
22-
2322
* [Bag](algs4/bag.go)
2423
* [Queue](algs4/queue.go)
2524
* [Stack](algs4/stack.go)
2625
* [UnionFind](algs4/uf.go)
27-
2826
* 2 SORTING
29-
3027
* [Selection](algs4/selection.go)
3128
* [Insertion](algs4/insertion.go)
3229
* [Shell](algs4/shell.go)
@@ -38,17 +35,14 @@ To test each algorithm(data structure), instead of running the file directly, yo
3835
* [IndexMinPQ](algs4/index_min_pq.go)
3936
* [Multiway](algs4/cmd/multiway/main.go)
4037
* [Heap](algs4/heap.go)
41-
4238
* 3 SEARCHING
43-
4439
* [FrequencyCounter](algs4/cmd/frequency-counter/main.go)
4540
* [SequentialSearchST](algs4/sequential_search.go)
4641
* [BinarySearchST](algs4/binary_search_st.go)
4742
* [BST](algs4/bst.go)
4843
* [RedBlackBST](algs4/red_black_bst.go)
4944
* [SeparateChainingHashST](algs4/separate_chaining_hash_st.go)
5045
* [LinearProbingHashST](algs4/linear_probing_hash_st.go)
51-
5246
* 4 GRAPHS
5347
* Graph
5448
* [Graph](algs4/graph.go)
@@ -77,12 +71,11 @@ To test each algorithm(data structure), instead of running the file directly, yo
7771
* [DijkstraSP](algs4/dijkstra_sp.go)
7872
* [AcyclicSP](algs4/acyclic_sp.go)
7973
* [BellmanFordSP](algs4/bellman_ford_sp.go)
80-
81-
8274
* 5 STRING
83-
8475
* [LSD](algs4/lsd.go)
8576
* [MSD](algs4/msd.go)
77+
* [Quick3string](algs4/quick3_string.go)
78+
* [TrieST](trie_st.go)
8679

8780

8881
## License

algs4/quick3_string.go

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package algs4
2+
3+
// Quick3String ...
4+
type Quick3String struct {
5+
CUTOFF int // cutoff to insertion sort
6+
R int // extended ASCII alphabet size
7+
aux []string
8+
}
9+
10+
// NewQuick3String ...
11+
func NewQuick3String(a []string) *Quick3String {
12+
m := &Quick3String{CUTOFF: 15, R: 256, aux: make([]string, len(a))}
13+
m.sort(a, 0, len(a)-1, 0)
14+
return m
15+
}
16+
17+
func (m *Quick3String) insertion(a []string, lo, hi, d int) {
18+
for i := lo; i <= hi; i++ {
19+
for j := i; j > lo && a[j][d] < a[j-1][d]; j-- {
20+
a[j], a[j-1] = a[j-1], a[j]
21+
}
22+
}
23+
}
24+
func (m *Quick3String) sort(a []string, lo, hi, d int) {
25+
if hi <= lo+m.CUTOFF {
26+
m.insertion(a, lo, hi, d)
27+
return
28+
}
29+
30+
lt, gt := lo, hi
31+
v := a[lo][d]
32+
for i := lo + 1; i <= gt; {
33+
t := a[i][d]
34+
if t < v {
35+
m.exch(a, lt, i)
36+
lt++
37+
i++
38+
} else if t > v {
39+
m.exch(a, i, gt)
40+
gt--
41+
} else {
42+
i++
43+
}
44+
}
45+
m.sort(a, lo, lt-1, d)
46+
if v >= 0 {
47+
m.sort(a, lt, gt, d+1)
48+
}
49+
m.sort(a, gt+1, hi, d)
50+
51+
}
52+
53+
func (m *Quick3String) exch(a []string, i, j int) {
54+
a[i], a[j] = a[j], a[i]
55+
}

algs4/trie_st.go

+174
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
package algs4
2+
3+
const radix = 256
4+
5+
type trieNode struct {
6+
val interface{}
7+
next []*trieNode
8+
}
9+
10+
func newNode() *trieNode {
11+
return &trieNode{next: make([]*trieNode, radix)}
12+
}
13+
14+
// TrieST ...
15+
type TrieST struct {
16+
R int
17+
n int // size
18+
root *trieNode
19+
}
20+
21+
// NewTrieST ...
22+
func NewTrieST() *TrieST {
23+
return &TrieST{radix, 0, nil}
24+
}
25+
26+
// Get ...
27+
func (t *TrieST) Get(key string) interface{} {
28+
x := t.get(t.root, key, 0)
29+
if x == nil {
30+
return nil
31+
}
32+
return x.val
33+
}
34+
35+
func (t *TrieST) get(x *trieNode, key string, d int) *trieNode {
36+
if x == nil {
37+
return nil
38+
}
39+
if d == len(key) {
40+
return x
41+
}
42+
c := key[d]
43+
return t.get(x.next[c], key, d+1)
44+
}
45+
46+
// Put ...
47+
func (t *TrieST) Put(key string, val interface{}) {
48+
t.root = t.put(t.root, key, val, 0)
49+
}
50+
51+
func (t *TrieST) put(x *trieNode, key string, val interface{}, d int) *trieNode {
52+
if x == nil {
53+
x = newNode()
54+
}
55+
if d == len(key) {
56+
if x.val == nil {
57+
t.n++
58+
}
59+
x.val = val
60+
return x
61+
}
62+
c := key[d]
63+
x.next[c] = t.put(x.next[c], key, val, d+1)
64+
return x
65+
}
66+
67+
// Keys ...
68+
func (t *TrieST) Keys() []string {
69+
return t.KeysWithPrefix("")
70+
}
71+
72+
// KeysWithPrefix ...
73+
func (t *TrieST) KeysWithPrefix(pre string) (keys []string) {
74+
q := NewQueue()
75+
t.collect(t.get(t.root, pre, 0), pre, q)
76+
for _, item := range q.Slice() {
77+
keys = append(keys, item.(string))
78+
}
79+
return
80+
}
81+
82+
func (t *TrieST) collect(x *trieNode, pre string, q *Queue) {
83+
if x == nil {
84+
return
85+
}
86+
if x.val != nil {
87+
q.Enqueue(pre)
88+
}
89+
for c := 0; c < t.R; c++ {
90+
t.collect(x.next[c], pre+string(c), q)
91+
}
92+
}
93+
94+
// KeysThatMatch ...
95+
func (t *TrieST) KeysThatMatch(pat string) (keys []string) {
96+
q := NewQueue()
97+
t.collectMatch(t.root, "", pat, q)
98+
for _, item := range q.Slice() {
99+
keys = append(keys, item.(string))
100+
}
101+
return
102+
}
103+
104+
func (t *TrieST) collectMatch(x *trieNode, pre, pat string, q *Queue) {
105+
if x == nil {
106+
return
107+
}
108+
d := len(pre)
109+
if d == len(pat) && x.val != nil {
110+
q.Enqueue(pre)
111+
}
112+
if d == len(pat) {
113+
return
114+
}
115+
next := pat[d]
116+
for c := 0; c < t.R; c++ {
117+
if string(next) == "." || int(next) == c {
118+
t.collectMatch(x.next[c], pre+string(c), pat, q)
119+
}
120+
}
121+
}
122+
123+
// LongPrefixOf ...
124+
func (t *TrieST) LongPrefixOf(s string) string {
125+
length := t.search(t.root, s, 0, 0)
126+
return s[:length]
127+
}
128+
func (t *TrieST) search(x *trieNode, s string, d, length int) int {
129+
if x == nil {
130+
return length
131+
}
132+
if x.val != nil {
133+
length = d
134+
}
135+
if d == len(s) {
136+
return length
137+
}
138+
c := s[d]
139+
return t.search(x.next[c], s, d+1, length)
140+
}
141+
142+
// Delete ...
143+
func (t *TrieST) Delete(key string) {
144+
t.root = t.delete(t.root, key, 0)
145+
}
146+
147+
func (t *TrieST) delete(x *trieNode, key string, d int) *trieNode {
148+
if x == nil {
149+
return nil
150+
}
151+
if d == len(key) {
152+
if x.val != nil {
153+
t.n--
154+
}
155+
x.val = nil
156+
} else {
157+
c := key[d]
158+
x.next[c] = t.delete(x.next[c], key, d+1)
159+
}
160+
if x.val == nil {
161+
return x
162+
}
163+
for c := 0; c < t.R; c++ {
164+
if x.next[c] != nil {
165+
return x
166+
}
167+
}
168+
return nil
169+
}
170+
171+
// Size ...
172+
func (t *TrieST) Size() int {
173+
return t.n
174+
}

cmd/quick3-string/main.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/******************************************************************************
2+
* Execution: go run cmd/quick3-string/main.go < input.txt
3+
* Data files: https://algs4.cs.princeton.edu/51radix/words3.txt
4+
* https://algs4.cs.princeton.edu/51radix/shells.txt
5+
*
6+
* Reads string from standard input and 3-way string quicksort them.
7+
*
8+
* % go run cmd/quick3-string/main.go < shells.txt
9+
* are
10+
* by
11+
* sea
12+
* seashells
13+
* seashells
14+
* sells
15+
* sells
16+
* she
17+
* she
18+
* shells
19+
* shore
20+
* surely
21+
* the
22+
* the
23+
*
24+
******************************************************************************/
25+
26+
package main
27+
28+
import (
29+
"fmt"
30+
31+
"github.com/shellfly/algo/algs4"
32+
"github.com/shellfly/algo/stdin"
33+
)
34+
35+
func main() {
36+
words := stdin.ReadAllStrings()
37+
algs4.NewQuick3String(words)
38+
fmt.Println(words)
39+
}

cmd/trie-st/main.go

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/******************************************************************************
2+
* Compilation: javac TrieST.java
3+
* Execution: java TrieST < words.txt
4+
* Dependencies: StdIn.java
5+
* Data files: https://algs4.cs.princeton.edviu/52trie/shellsST.txt
6+
*
7+
* A string symbol table for extended ASCII strings, implemented
8+
* using a 256-way trie.
9+
*
10+
* % java TrieST < shellsST.txt
11+
* by 4
12+
* sea 6
13+
* sells 1
14+
* she 0
15+
* shells 3
16+
* shore 7
17+
* the 5
18+
*
19+
******************************************************************************/
20+
21+
package main
22+
23+
import (
24+
"fmt"
25+
26+
"github.com/shellfly/algo/algs4"
27+
"github.com/shellfly/algo/stdin"
28+
)
29+
30+
func main() {
31+
st := algs4.NewTrieST()
32+
in := stdin.NewStdIn()
33+
for i := 0; !in.IsEmpty(); i++ {
34+
key := in.ReadString()
35+
st.Put(key, i)
36+
}
37+
38+
// print results
39+
if st.Size() < 100 {
40+
fmt.Println("keys(\"\"):")
41+
for _, key := range st.Keys() {
42+
fmt.Println(key, " ", st.Get(key))
43+
}
44+
fmt.Println()
45+
}
46+
47+
fmt.Println("longestPrefixOf(\"shellsort\"):")
48+
fmt.Println(st.LongPrefixOf("shellsort"))
49+
fmt.Println()
50+
51+
fmt.Println("longestPrefixOf(\"quicksort\"):")
52+
fmt.Println(st.LongPrefixOf("quicksort"))
53+
fmt.Println()
54+
55+
fmt.Println("keysWithPrefix(\"shor\"):")
56+
for _, s := range st.KeysWithPrefix("shor") {
57+
fmt.Println(s)
58+
}
59+
fmt.Println()
60+
61+
fmt.Println("keysThatMatch(\".he.l.\"):")
62+
for _, s := range st.KeysThatMatch(".he.l.") {
63+
fmt.Println(s)
64+
}
65+
}

0 commit comments

Comments
 (0)