-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathorderedset.go
More file actions
163 lines (140 loc) · 4.31 KB
/
Copy pathorderedset.go
File metadata and controls
163 lines (140 loc) · 4.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package container
import "fmt"
// OrderedSet is a hash set with the preservation of insertion order
type OrderedSet[K comparable] OrderedMap[K, struct{}]
// NewOrderedSet returns a new OrderedSet object
func NewOrderedSet[K comparable]() *OrderedSet[K] {
m := NewOrderedMap[K,struct{}]()
return (*OrderedSet[K])(m)
}
// Has the given key in the OrderedSet
func (s *OrderedSet[K]) Has(k K) bool {
m := (*OrderedMap[K, struct{}])(s)
return m.Has(k)
}
// Insert a key into the OrderedSet
func (s *OrderedSet[K]) Insert(k K) {
m := (*OrderedMap[K, struct{}])(s)
m.Insert(k, struct{}{})
}
// Remove the given key, returns if the key exists.
func (s *OrderedSet[K]) Remove(k K) bool {
m := (*OrderedMap[K, struct{}])(s)
_, ok := m.Remove(k)
return ok
}
// Clear all elements in the OrderedSet
func (s *OrderedSet[K]) Clear() {
m := (*OrderedMap[K, struct{}])(s)
m.Clear()
}
// Move to an element with given key to the tail of the OrderedSet
// the given key must exist in the OrderedSet
func (s *OrderedSet[K]) MoveToBack(k K) {
m := (*OrderedMap[K, struct{}])(s)
m.MoveToBack(k)
}
// Move to an element with given key to the head of the OrderedSet
// the given key must exist in the OrderedSet
func (s *OrderedSet[K]) MoveToFront(k K) {
m := (*OrderedMap[K, struct{}])(s)
m.MoveToFront(k)
}
// Removes the tail element of the OrderedSet and returns the key
// and if the tail element exists.
// The tail element doesn't exist if and only if the OrderedSet is empty.
func (s *OrderedSet[K]) PopBack() (k K, ok bool) {
m := (*OrderedMap[K, struct{}])(s)
k, _, ok = m.PopBack()
return
}
// Removes the head element of the OrderedSet and returns the key
// and if the head element exists.
// The head element doesn't exist if and only if the OrderedSet is empty.
func (s *OrderedSet[K]) PopFront() (k K, ok bool) {
m := (*OrderedMap[K, struct{}])(s)
k, _, ok = m.PopFront()
return
}
// Len returns the size of the OrderedSet
func (s *OrderedSet[K]) Len() int {
m := (*OrderedMap[K, struct{}])(s)
return m.Len()
}
/////////////////////////////
///////// Testing ///////////
/////////////////////////////
func checkOSetSize(s *OrderedSet[string], expect int) {
if s.Len() != expect {
panic(fmt.Sprintf("Len check failed, got %d, expect, %d", s.Len(), expect))
}
}
func checkOSetOrder(s *OrderedSet[string], expKeys []string) {
checkOSetSize(s, len(expKeys))
m := (*OrderedMap[string, struct{}])(s)
for i, e1 := 0, m.list.Front(); e1 != nil; i, e1 = i+1, e1.Next() {
k := expKeys[i]
if e2, ok := m.mp[k]; !ok || e1 != e2 {
if !ok {
panic(fmt.Sprintf("Key %v should be in map but missed", k))
}
if e1 != e2 {
panic(fmt.Sprintf("map and list point to different elements for key %v", k))
}
}
if k != e1.Value.Key {
panic(fmt.Sprintf("element entry failed, got (k): (%v), expected (%v)", e1.Value.Key, k))
}
}
}
func checkOSetK(gotK string, gotOk bool, expK string, expOk bool) {
if gotK != expK || gotOk != expOk {
panic(fmt.Sprintf("k,ok does not match where key:(%v,%v), ok:(%v,%v)",
gotK, expK, gotOk, expOk))
}
}
func testOrderedSet() {
var k string
var ok bool
s:= NewOrderedSet[string]()
checkOSetOrder(s, []string{})
// single element
s.Insert("apple")
checkOSetOrder(s, []string{"apple"})
ok = s.Has("apple")
checkOSetK(k, ok, k, true)
s.Insert("apple")
checkOSetOrder(s, []string{"apple"})
s.MoveToFront("apple")
checkOSetOrder(s, []string{"apple"})
s.MoveToBack("apple")
checkOSetOrder(s, []string{"apple"})
ok = s.Remove("apple")
checkOSetK(k, ok, k, true)
checkOSetOrder(s, []string{})
ok = s.Has("banana")
checkOSetK(k, ok, k, false)
// multiple elements
s.Insert("apple")
s.Insert("banana")
s.Insert("cherry")
checkOSetOrder(s, []string{"apple", "banana", "cherry"})
s.MoveToBack("banana")
checkOSetOrder(s, []string{"apple", "cherry", "banana"})
s.MoveToFront("cherry")
checkOSetOrder(s, []string{"cherry", "apple", "banana"})
s.Insert("cherry")
checkOSetOrder(s, []string{"cherry", "apple", "banana"})
k, ok = s.PopFront()
checkOSetK(k, ok, "cherry", true)
checkOSetOrder(s, []string{"apple", "banana"})
s.Insert("cherry")
checkOSetOrder(s, []string{"apple", "banana", "cherry"})
k, ok = s.PopBack()
checkOSetK(k, ok, "cherry", true)
checkOSetOrder(s, []string{"apple", "banana"})
ok = s.Remove("banana")
checkOSetK(k, ok, k,true)
s.Clear()
checkOSetOrder(s, []string{})
}