stakach-algorithms 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,273 +1,273 @@
1
- require 'containers/stack'
2
- =begin rdoc
3
- A SplayTreeMap is a map that is stored in ascending order of its keys, determined by applying
4
- the function <=> to compare keys. No duplicate values for keys are allowed, so new values of a key
5
- overwrites the old value of the key.
6
-
7
- A major advantage of SplayTreeMap over a Hash is the fact that keys are stored in order and can thus be
8
- iterated over in order. Also, Splay Trees are self-optimizing as recently accessed nodes stay near
9
- the root and are easily re-accessed later. Splay Trees are also more simply implemented than Red-Black
10
- trees.
11
-
12
- Splay trees have amortized O(log n) performance for most methods, but are O(n) worst case. This happens
13
- when keys are added in sorted order, causing the tree to have a height of the number of items added.
14
-
15
- =end
16
- module Algorithms
17
- module Containers
18
- class RubySplayTreeMap
19
- include Enumerable
20
-
21
- Node = Struct.new(:key, :value, :left, :right)
22
-
23
- # Create and initialize a new empty SplayTreeMap.
24
- def initialize
25
- @size = 0
26
- clear
27
- end
28
-
29
- # Insert an item with an associated key into the SplayTreeMap, and returns the item inserted
30
- #
31
- # Complexity: amortized O(log n)
32
- #
33
- # map = Algorithms::Containers::SplayTreeMap.new
34
- # map.push("MA", "Massachusetts") #=> "Massachusetts"
35
- # map.get("MA") #=> "Massachusetts"
36
- def push(key, value)
37
- if @root.nil?
38
- @root = Node.new(key, value, nil, nil)
39
- @size = 1
40
- return value
41
- end
42
- splay(key)
43
-
44
- cmp = (key <=> @root.key)
45
- if cmp == 0
46
- @root.value = value
47
- return value
48
- end
49
- node = Node.new(key, value, nil, nil)
50
- if cmp < 1
51
- node.left = @root.left
52
- node.right = @root
53
- @root.left = nil
54
- else
55
- node.right = @root.right
56
- node.left = @root
57
- @root.right = nil
58
- end
59
- @root = node
60
- @size += 1
61
- value
62
- end
63
- alias_method :[]=, :push
64
-
65
- # Return the number of items in the SplayTreeMap.
66
- #
67
- # map = Algorithms::Containers::SplayTreeMap.new
68
- # map.push("MA", "Massachusetts")
69
- # map.push("GA", "Georgia")
70
- # map.size #=> 2
71
- def size
72
- @size
73
- end
74
-
75
- # Remove all elements from the SplayTreeMap
76
- #
77
- # Complexity: O(1)
78
- #
79
- def clear
80
- @root = nil
81
- @size = 0
82
- @header = Node.new(nil, nil, nil, nil)
83
- end
84
-
85
- # Return the height of the tree structure in the SplayTreeMap.
86
- #
87
- # Complexity: O(log n)
88
- #
89
- # map = Algorithms::Containers::SplayTreeMap.new
90
- # map.push("MA", "Massachusetts")
91
- # map.push("GA", "Georgia")
92
- # map.height #=> 2
93
- def height
94
- height_recursive(@root)
95
- end
96
-
97
- # Return true if key is found in the SplayTreeMap, false otherwise.
98
- #
99
- # Complexity: amortized O(log n)
100
- #
101
- # map = Algorithms::Containers::SplayTreeMap.new
102
- # map["MA"] = "Massachusetts"
103
- # map["GA"] = "Georgia"
104
- # map.has_key?("GA") #=> true
105
- # map.has_key?("DE") #=> false
106
- def has_key?(key)
107
- !get(key).nil?
108
- end
109
-
110
- # Return the item associated with the key, or nil if none found.
111
- #
112
- # Complexity: amortized O(log n)
113
- #
114
- # map = Algorithms::Containers::SplayTreeMap.new
115
- # map.push("MA", "Massachusetts")
116
- # map.push("GA", "Georgia")
117
- # map.get("GA") #=> "Georgia"
118
- def get(key)
119
- return nil if @root.nil?
120
-
121
- splay(key)
122
- (@root.key <=> key) == 0 ? @root.value : nil
123
- end
124
- alias_method :[], :get
125
-
126
- # Return the smallest [key, value] pair in the SplayTreeMap, or nil if the tree is empty.
127
- #
128
- # Complexity: amortized O(log n)
129
- #
130
- # map = Algorithms::Containers::SplayTreeMap.new
131
- # map["MA"] = "Massachusetts"
132
- # map["GA"] = "Georgia"
133
- # map.min #=> ["GA", "Georgia"]
134
- def min
135
- return nil if @root.nil?
136
- n = @root
137
- while n.left
138
- n = n.left
139
- end
140
- splay(n.key)
141
- return [n.key, n.value]
142
- end
143
-
144
- # Return the largest [key, value] pair in the SplayTreeMap, or nil if the tree is empty.
145
- #
146
- # Complexity: amortized O(log n)
147
- #
148
- # map = Algorithms::Containers::SplayTreeMap.new
149
- # map["MA"] = "Massachusetts"
150
- # map["GA"] = "Georgia"
151
- # map.max #=> ["MA", "Massachusetts"]
152
- def max
153
- return nil if @root.nil?
154
- n = @root
155
- while n.right
156
- n = n.right
157
- end
158
- splay(n.key)
159
- return [n.key, n.value]
160
- end
161
-
162
- # Deletes the item and key if it's found, and returns the item. Returns nil
163
- # if key is not present.
164
- #
165
- # Complexity: amortized O(log n)
166
- #
167
- # map = Algorithms::Containers::SplayTreeMap.new
168
- # map["MA"] = "Massachusetts"
169
- # map["GA"] = "Georgia"
170
- # map.delete("GA") #=> "Georgia"
171
- # map.delete("DE") #=> nil
172
- def delete(key)
173
- return nil if @root.nil?
174
- deleted = nil
175
- splay(key)
176
- if (key <=> @root.key) == 0 # The key exists
177
- deleted = @root.value
178
- if @root.left.nil?
179
- @root = @root.right
180
- else
181
- x = @root.right
182
- @root = @root.left
183
- splay(key)
184
- @root.right = x
185
- end
186
- end
187
- deleted
188
- end
189
-
190
- # Iterates over the SplayTreeMap in ascending order. Uses an iterative, not recursive, approach.
191
- def each
192
- return nil unless @root
193
- stack = Stack.new
194
- cursor = @root
195
- loop do
196
- if cursor
197
- stack.push(cursor)
198
- cursor = cursor.left
199
- else
200
- unless stack.empty?
201
- cursor = stack.pop
202
- yield(cursor.key, cursor.value)
203
- cursor = cursor.right
204
- else
205
- break
206
- end
207
- end
208
- end
209
- end
210
-
211
- # Moves a key to the root, updating the structure in each step.
212
- def splay(key)
213
- l, r = @header, @header
214
- t = @root
215
- @header.left, @header.right = nil, nil
216
-
217
- loop do
218
- if (key <=> t.key) == -1
219
- break unless t.left
220
- if (key <=> t.left.key) == -1
221
- y = t.left
222
- t.left = y.right
223
- y.right = t
224
- t = y
225
- break unless t.left
226
- end
227
- r.left = t
228
- r = t
229
- t = t.left
230
- elsif (key <=> t.key) == 1
231
- break unless t.right
232
- if (key <=> t.right.key) == 1
233
- y = t.right
234
- t.right = y.left
235
- y.left = t
236
- t = y
237
- break unless t.right
238
- end
239
- l.right = t
240
- l = t
241
- t = t.right
242
- else
243
- break
244
- end
245
- end
246
- l.right = t.left
247
- r.left = t.right
248
- t.left = @header.right
249
- t.right = @header.left
250
- @root = t
251
- end
252
- private :splay
253
-
254
- # Recursively determine height
255
- def height_recursive(node)
256
- return 0 if node.nil?
257
-
258
- left_height = 1 + height_recursive(node.left)
259
- right_height = 1 + height_recursive(node.right)
260
-
261
- left_height > right_height ? left_height : right_height
262
- end
263
- private :height_recursive
264
- end
265
- end
266
-
267
- begin
268
- require 'CSplayTreeMap'
269
- Containers::SplayTreeMap = Containers::CSplayTreeMap
270
- rescue LoadError # C Version could not be found, try ruby version
271
- Containers::SplayTreeMap = Containers::RubySplayTreeMap
272
- end
273
- end
1
+ require 'containers/stack'
2
+ =begin rdoc
3
+ A SplayTreeMap is a map that is stored in ascending order of its keys, determined by applying
4
+ the function <=> to compare keys. No duplicate values for keys are allowed, so new values of a key
5
+ overwrites the old value of the key.
6
+
7
+ A major advantage of SplayTreeMap over a Hash is the fact that keys are stored in order and can thus be
8
+ iterated over in order. Also, Splay Trees are self-optimizing as recently accessed nodes stay near
9
+ the root and are easily re-accessed later. Splay Trees are also more simply implemented than Red-Black
10
+ trees.
11
+
12
+ Splay trees have amortized O(log n) performance for most methods, but are O(n) worst case. This happens
13
+ when keys are added in sorted order, causing the tree to have a height of the number of items added.
14
+
15
+ =end
16
+ module Algorithms
17
+ module Containers
18
+ class RubySplayTreeMap
19
+ include Enumerable
20
+
21
+ Node = Struct.new(:key, :value, :left, :right)
22
+
23
+ # Create and initialize a new empty SplayTreeMap.
24
+ def initialize
25
+ @size = 0
26
+ clear
27
+ end
28
+
29
+ # Insert an item with an associated key into the SplayTreeMap, and returns the item inserted
30
+ #
31
+ # Complexity: amortized O(log n)
32
+ #
33
+ # map = Algorithms::Containers::SplayTreeMap.new
34
+ # map.push("MA", "Massachusetts") #=> "Massachusetts"
35
+ # map.get("MA") #=> "Massachusetts"
36
+ def push(key, value)
37
+ if @root.nil?
38
+ @root = Node.new(key, value, nil, nil)
39
+ @size = 1
40
+ return value
41
+ end
42
+ splay(key)
43
+
44
+ cmp = (key <=> @root.key)
45
+ if cmp == 0
46
+ @root.value = value
47
+ return value
48
+ end
49
+ node = Node.new(key, value, nil, nil)
50
+ if cmp < 1
51
+ node.left = @root.left
52
+ node.right = @root
53
+ @root.left = nil
54
+ else
55
+ node.right = @root.right
56
+ node.left = @root
57
+ @root.right = nil
58
+ end
59
+ @root = node
60
+ @size += 1
61
+ value
62
+ end
63
+ alias_method :[]=, :push
64
+
65
+ # Return the number of items in the SplayTreeMap.
66
+ #
67
+ # map = Algorithms::Containers::SplayTreeMap.new
68
+ # map.push("MA", "Massachusetts")
69
+ # map.push("GA", "Georgia")
70
+ # map.size #=> 2
71
+ def size
72
+ @size
73
+ end
74
+
75
+ # Remove all elements from the SplayTreeMap
76
+ #
77
+ # Complexity: O(1)
78
+ #
79
+ def clear
80
+ @root = nil
81
+ @size = 0
82
+ @header = Node.new(nil, nil, nil, nil)
83
+ end
84
+
85
+ # Return the height of the tree structure in the SplayTreeMap.
86
+ #
87
+ # Complexity: O(log n)
88
+ #
89
+ # map = Algorithms::Containers::SplayTreeMap.new
90
+ # map.push("MA", "Massachusetts")
91
+ # map.push("GA", "Georgia")
92
+ # map.height #=> 2
93
+ def height
94
+ height_recursive(@root)
95
+ end
96
+
97
+ # Return true if key is found in the SplayTreeMap, false otherwise.
98
+ #
99
+ # Complexity: amortized O(log n)
100
+ #
101
+ # map = Algorithms::Containers::SplayTreeMap.new
102
+ # map["MA"] = "Massachusetts"
103
+ # map["GA"] = "Georgia"
104
+ # map.has_key?("GA") #=> true
105
+ # map.has_key?("DE") #=> false
106
+ def has_key?(key)
107
+ !get(key).nil?
108
+ end
109
+
110
+ # Return the item associated with the key, or nil if none found.
111
+ #
112
+ # Complexity: amortized O(log n)
113
+ #
114
+ # map = Algorithms::Containers::SplayTreeMap.new
115
+ # map.push("MA", "Massachusetts")
116
+ # map.push("GA", "Georgia")
117
+ # map.get("GA") #=> "Georgia"
118
+ def get(key)
119
+ return nil if @root.nil?
120
+
121
+ splay(key)
122
+ (@root.key <=> key) == 0 ? @root.value : nil
123
+ end
124
+ alias_method :[], :get
125
+
126
+ # Return the smallest [key, value] pair in the SplayTreeMap, or nil if the tree is empty.
127
+ #
128
+ # Complexity: amortized O(log n)
129
+ #
130
+ # map = Algorithms::Containers::SplayTreeMap.new
131
+ # map["MA"] = "Massachusetts"
132
+ # map["GA"] = "Georgia"
133
+ # map.min #=> ["GA", "Georgia"]
134
+ def min
135
+ return nil if @root.nil?
136
+ n = @root
137
+ while n.left
138
+ n = n.left
139
+ end
140
+ splay(n.key)
141
+ return [n.key, n.value]
142
+ end
143
+
144
+ # Return the largest [key, value] pair in the SplayTreeMap, or nil if the tree is empty.
145
+ #
146
+ # Complexity: amortized O(log n)
147
+ #
148
+ # map = Algorithms::Containers::SplayTreeMap.new
149
+ # map["MA"] = "Massachusetts"
150
+ # map["GA"] = "Georgia"
151
+ # map.max #=> ["MA", "Massachusetts"]
152
+ def max
153
+ return nil if @root.nil?
154
+ n = @root
155
+ while n.right
156
+ n = n.right
157
+ end
158
+ splay(n.key)
159
+ return [n.key, n.value]
160
+ end
161
+
162
+ # Deletes the item and key if it's found, and returns the item. Returns nil
163
+ # if key is not present.
164
+ #
165
+ # Complexity: amortized O(log n)
166
+ #
167
+ # map = Algorithms::Containers::SplayTreeMap.new
168
+ # map["MA"] = "Massachusetts"
169
+ # map["GA"] = "Georgia"
170
+ # map.delete("GA") #=> "Georgia"
171
+ # map.delete("DE") #=> nil
172
+ def delete(key)
173
+ return nil if @root.nil?
174
+ deleted = nil
175
+ splay(key)
176
+ if (key <=> @root.key) == 0 # The key exists
177
+ deleted = @root.value
178
+ if @root.left.nil?
179
+ @root = @root.right
180
+ else
181
+ x = @root.right
182
+ @root = @root.left
183
+ splay(key)
184
+ @root.right = x
185
+ end
186
+ end
187
+ deleted
188
+ end
189
+
190
+ # Iterates over the SplayTreeMap in ascending order. Uses an iterative, not recursive, approach.
191
+ def each
192
+ return nil unless @root
193
+ stack = Stack.new
194
+ cursor = @root
195
+ loop do
196
+ if cursor
197
+ stack.push(cursor)
198
+ cursor = cursor.left
199
+ else
200
+ unless stack.empty?
201
+ cursor = stack.pop
202
+ yield(cursor.key, cursor.value)
203
+ cursor = cursor.right
204
+ else
205
+ break
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ # Moves a key to the root, updating the structure in each step.
212
+ def splay(key)
213
+ l, r = @header, @header
214
+ t = @root
215
+ @header.left, @header.right = nil, nil
216
+
217
+ loop do
218
+ if (key <=> t.key) == -1
219
+ break unless t.left
220
+ if (key <=> t.left.key) == -1
221
+ y = t.left
222
+ t.left = y.right
223
+ y.right = t
224
+ t = y
225
+ break unless t.left
226
+ end
227
+ r.left = t
228
+ r = t
229
+ t = t.left
230
+ elsif (key <=> t.key) == 1
231
+ break unless t.right
232
+ if (key <=> t.right.key) == 1
233
+ y = t.right
234
+ t.right = y.left
235
+ y.left = t
236
+ t = y
237
+ break unless t.right
238
+ end
239
+ l.right = t
240
+ l = t
241
+ t = t.right
242
+ else
243
+ break
244
+ end
245
+ end
246
+ l.right = t.left
247
+ r.left = t.right
248
+ t.left = @header.right
249
+ t.right = @header.left
250
+ @root = t
251
+ end
252
+ private :splay
253
+
254
+ # Recursively determine height
255
+ def height_recursive(node)
256
+ return 0 if node.nil?
257
+
258
+ left_height = 1 + height_recursive(node.left)
259
+ right_height = 1 + height_recursive(node.right)
260
+
261
+ left_height > right_height ? left_height : right_height
262
+ end
263
+ private :height_recursive
264
+ end
265
+ end
266
+
267
+ begin
268
+ require 'CSplayTreeMap'
269
+ Containers::SplayTreeMap = Containers::CSplayTreeMap
270
+ rescue # C Version could not be found, try ruby version
271
+ Containers::SplayTreeMap = Containers::RubySplayTreeMap
272
+ end
273
+ end