depq 0.3 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README +38 -22
- data/{depq.rb → lib/depq.rb} +591 -474
- data/{test-depq.rb → test/test-depq.rb} +70 -25
- metadata +5 -5
data/README
CHANGED
@@ -1,19 +1,22 @@
|
|
1
|
-
= Depq -
|
1
|
+
= Depq - Double-Ended Priority Queue
|
2
2
|
|
3
|
-
|
3
|
+
depq is double-ended stable priority queue with priority update operation implemented using implicit heap.
|
4
|
+
|
5
|
+
== Features
|
4
6
|
|
5
7
|
* queue - you can insert and delete values
|
6
8
|
* priority - you can get a value with minimum priority
|
7
9
|
* double-ended - you can get a value with maximum priority too
|
8
|
-
* stable - you
|
9
|
-
* update
|
10
|
-
* implicit
|
10
|
+
* stable - you will get the value inserted first with minimum/maximum priority
|
11
|
+
* priority update - usable for Dijkstra's shortest path algorithm and various graph algorithms
|
12
|
+
* implicit heap - compact heap representation using array. most operations are O(log n) at worst
|
13
|
+
* iterator operations: nlargest, nsmallest and merge
|
11
14
|
|
12
|
-
|
15
|
+
== Install
|
13
16
|
|
14
17
|
gem install depq
|
15
18
|
|
16
|
-
|
19
|
+
== Links
|
17
20
|
|
18
21
|
* ((<reference manual|URL:http://depq.rubyforge.org/rdoc/classes/Depq.html>))
|
19
22
|
* ((<home page on rubyforge|URL:http://depq.rubyforge.org/>))
|
@@ -21,12 +24,12 @@
|
|
21
24
|
* ((<source repository on github|URL:http://github.com/akr/depq>))
|
22
25
|
* ((<raa entry|URL:http://raa.ruby-lang.org/project/depq/>))
|
23
26
|
|
24
|
-
|
27
|
+
== Introduction
|
25
28
|
|
26
|
-
|
29
|
+
=== Simple Insertion/Deletion
|
27
30
|
|
28
31
|
You can insert values into a Depq object.
|
29
|
-
You can
|
32
|
+
You can delete the values from the object from ascending/descending order.
|
30
33
|
delete_min deletes the minimum value.
|
31
34
|
It is used for ascending order.
|
32
35
|
|
@@ -47,7 +50,7 @@ delete_max is similar to delete_min except it deletes maximum element
|
|
47
50
|
instead of minimum.
|
48
51
|
It is used for descending order.
|
49
52
|
|
50
|
-
|
53
|
+
=== The Order
|
51
54
|
|
52
55
|
The order is defined by the priorities corresponds to the values and
|
53
56
|
comparison operator specified for the queue.
|
@@ -64,8 +67,7 @@ comparison operator specified for the queue.
|
|
64
67
|
If there are multiple values with same priority, subpriority is used to compare them.
|
65
68
|
subpriority is an integer which can be specified by 3rd argument of insert.
|
66
69
|
If it is not specified, total number of inserted elements is used.
|
67
|
-
So Depq is "stable"
|
68
|
-
The element inserted first is minimum and deleted first.
|
70
|
+
So Depq is "stable" which means that the element inserted first is deleted first.
|
69
71
|
|
70
72
|
q = Depq.new
|
71
73
|
q.insert "a", 1 # "a", "c" and "e" has same priority: 1
|
@@ -81,22 +83,36 @@ The element inserted first is minimum and deleted first.
|
|
81
83
|
p q.delete_min #=> "c"
|
82
84
|
p q.delete_min #=> "e" last element with priority 1
|
83
85
|
|
84
|
-
|
86
|
+
delete_max is also stable.
|
85
87
|
This means delete_max deletes the element with maximum priority with "minimum" subpriority.
|
86
88
|
|
87
|
-
|
89
|
+
q = Depq.new
|
90
|
+
q.insert "a", 1 # "a", "c" and "e" has same priority: 1
|
91
|
+
q.insert "b", 0 # "b", "d" and "f" has same priority: 0
|
92
|
+
q.insert "c", 1
|
93
|
+
q.insert "d", 0
|
94
|
+
q.insert "e", 1
|
95
|
+
q.insert "f", 0
|
96
|
+
p q.delete_max #=> "a" first element with priority 1
|
97
|
+
p q.delete_max #=> "c"
|
98
|
+
p q.delete_max #=> "e" last element with priority 1
|
99
|
+
p q.delete_max #=> "b" first element with priority 0
|
100
|
+
p q.delete_max #=> "d"
|
101
|
+
p q.delete_max #=> "f" last element with priority 0
|
102
|
+
|
103
|
+
=== Update Element
|
88
104
|
|
89
105
|
An inserted element can be modified and/or deleted.
|
90
|
-
|
106
|
+
The element to be modified is specified by Depq::Locator object.
|
91
107
|
It is returned by insert, find_min_locator, etc.
|
92
108
|
|
93
109
|
q = Depq.new
|
94
110
|
d = q.insert "durian", 1
|
95
111
|
m = q.insert "mangosteen", 2
|
96
112
|
c = q.insert "cherry", 3
|
97
|
-
p m
|
98
|
-
p m.value
|
99
|
-
p m.priority
|
113
|
+
p m #=> #<Depq::Locator: "mangosteen":2>
|
114
|
+
p m.value #=> "mangosteen"
|
115
|
+
p m.priority #=> 2
|
100
116
|
p q.find_min #=> "durian"
|
101
117
|
p q.find_min_locator #=> #<Depq::Locator: "durian":1>
|
102
118
|
m.update("mangosteen", 0)
|
@@ -151,18 +167,18 @@ A* search algorithm, etc.
|
|
151
167
|
# [["A", "B", "C"], 3],
|
152
168
|
# [["A", "B", "C", "D"], 4]]
|
153
169
|
|
154
|
-
|
170
|
+
== Internal Heap Algorithm
|
155
171
|
|
156
172
|
Depq uses min-heap, max-heap or interval-heap internally.
|
157
173
|
When delete_min is used, min-heap is constructed.
|
158
174
|
When delete_max is used, max-heap is constructed.
|
159
175
|
When delete_min and delete_max is used, interval-heap is constructed.
|
160
176
|
|
161
|
-
|
177
|
+
== Author
|
162
178
|
|
163
179
|
Tanaka Akira <akr@fsij.org>
|
164
180
|
|
165
|
-
|
181
|
+
== License
|
166
182
|
|
167
183
|
Redistribution and use in source and binary forms, with or without
|
168
184
|
modification, are permitted provided that the following conditions are met:
|
data/{depq.rb → lib/depq.rb}
RENAMED
@@ -24,23 +24,26 @@
|
|
24
24
|
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
25
25
|
# OF SUCH DAMAGE.
|
26
26
|
|
27
|
-
# Depq - Double-Ended Priority Queue
|
27
|
+
# = Depq - Double-Ended Priority Queue
|
28
28
|
#
|
29
|
-
#
|
29
|
+
# depq is double-ended stable priority queue with priority update operation implemented using implicit heap.
|
30
|
+
#
|
31
|
+
# == Features
|
30
32
|
#
|
31
33
|
# * queue - you can insert and delete values
|
32
34
|
# * priority - you can get a value with minimum priority
|
33
35
|
# * double-ended - you can get a value with maximum priority too
|
34
|
-
# * stable - you
|
35
|
-
# * update
|
36
|
-
# * implicit
|
36
|
+
# * stable - you will get the value inserted first with minimum/maximum priority
|
37
|
+
# * priority update - usable for Dijkstra's shortest path algorithm and various graph algorithms
|
38
|
+
# * implicit heap - compact heap representation using array. most operations are O(log n) at worst
|
39
|
+
# * iterator operations: nlargest, nsmallest and merge
|
37
40
|
#
|
38
|
-
#
|
41
|
+
# == Introduction
|
39
42
|
#
|
40
|
-
#
|
43
|
+
# === Simple Insertion/Deletion
|
41
44
|
#
|
42
45
|
# You can insert values into a Depq object.
|
43
|
-
# You can
|
46
|
+
# You can delete the values from the object from ascending/descending order.
|
44
47
|
# delete_min deletes the minimum value.
|
45
48
|
# It is used for ascending order.
|
46
49
|
#
|
@@ -61,13 +64,13 @@
|
|
61
64
|
# instead of minimum.
|
62
65
|
# It is used for descending order.
|
63
66
|
#
|
64
|
-
#
|
67
|
+
# === The Order
|
65
68
|
#
|
66
|
-
# The order is defined by the priorities
|
69
|
+
# The order is defined by the priorities corresponds to the values and
|
67
70
|
# comparison operator specified for the queue.
|
68
71
|
#
|
69
72
|
# q = Depq.new(:casecmp) # use casecmp instead of <=>.
|
70
|
-
# q.
|
73
|
+
# q.insert 1, "Foo" # specify the priority for 1 as "Foo"
|
71
74
|
# q.insert 2, "bar"
|
72
75
|
# q.insert 3, "Baz"
|
73
76
|
# p q.delete_min #=> 2 # "bar" is minimum
|
@@ -78,8 +81,7 @@
|
|
78
81
|
# If there are multiple values with same priority, subpriority is used to compare them.
|
79
82
|
# subpriority is an integer which can be specified by 3rd argument of insert.
|
80
83
|
# If it is not specified, total number of inserted elements is used.
|
81
|
-
# So Depq is "stable"
|
82
|
-
# The element inserted first is minimum and deleted first.
|
84
|
+
# So Depq is "stable" which means that the element inserted first is deleted first.
|
83
85
|
#
|
84
86
|
# q = Depq.new
|
85
87
|
# q.insert "a", 1 # "a", "c" and "e" has same priority: 1
|
@@ -98,10 +100,24 @@
|
|
98
100
|
# Note that delete_max is also stable.
|
99
101
|
# This means delete_max deletes the element with maximum priority with "minimum" subpriority.
|
100
102
|
#
|
101
|
-
#
|
103
|
+
# q = Depq.new
|
104
|
+
# q.insert "a", 1 # "a", "c" and "e" has same priority: 1
|
105
|
+
# q.insert "b", 0 # "b", "d" and "f" has same priority: 0
|
106
|
+
# q.insert "c", 1
|
107
|
+
# q.insert "d", 0
|
108
|
+
# q.insert "e", 1
|
109
|
+
# q.insert "f", 0
|
110
|
+
# p q.delete_max #=> "a" first element with priority 1
|
111
|
+
# p q.delete_max #=> "c"
|
112
|
+
# p q.delete_max #=> "e" last element with priority 1
|
113
|
+
# p q.delete_max #=> "b" first element with priority 0
|
114
|
+
# p q.delete_max #=> "d"
|
115
|
+
# p q.delete_max #=> "f" last element with priority 0
|
116
|
+
#
|
117
|
+
# === Update Element
|
102
118
|
#
|
103
119
|
# An inserted element can be modified and/or deleted.
|
104
|
-
#
|
120
|
+
# The element to be modified is specified by Depq::Locator object.
|
105
121
|
# It is returned by insert, find_min_locator, etc.
|
106
122
|
#
|
107
123
|
# q = Depq.new
|
@@ -165,7 +181,7 @@
|
|
165
181
|
# # [["A", "B", "C"], 3],
|
166
182
|
# # [["A", "B", "C", "D"], 4]]
|
167
183
|
#
|
168
|
-
#
|
184
|
+
# == Internal Heap Algorithm
|
169
185
|
#
|
170
186
|
# Depq uses min-heap, max-heap or interval-heap internally.
|
171
187
|
# When delete_min is used, min-heap is constructed.
|
@@ -215,6 +231,12 @@ class Depq
|
|
215
231
|
define_method(:hash, Object.instance_method(:hash))
|
216
232
|
|
217
233
|
# Create a Depq::Locator object.
|
234
|
+
#
|
235
|
+
# loc = Depq::Locator.new("a", 1, 2)
|
236
|
+
# p loc.value #=> "a"
|
237
|
+
# p loc.priority #=> 1
|
238
|
+
# p loc.subpriority #=> 2
|
239
|
+
#
|
218
240
|
def initialize(value, priority=value, subpriority=nil)
|
219
241
|
super value, subpriority, priority
|
220
242
|
end
|
@@ -245,7 +267,7 @@ class Depq
|
|
245
267
|
|
246
268
|
# returns the queue.
|
247
269
|
#
|
248
|
-
# nil is returned if the locator is not in a
|
270
|
+
# nil is returned if the locator is not in a queue.
|
249
271
|
def depq
|
250
272
|
in_queue? ? depq_or_subpriority() : nil
|
251
273
|
end
|
@@ -374,7 +396,7 @@ class Depq
|
|
374
396
|
# Create a Depq object.
|
375
397
|
#
|
376
398
|
# The optional argument, cmp, specify the method to compare priorities.
|
377
|
-
# It should be a symbol or a Proc which takes two arguments.
|
399
|
+
# It should be a symbol or a comparator like a Proc which takes two arguments and returns -1, 0, 1.
|
378
400
|
# If it is omitted, :<=> is used.
|
379
401
|
#
|
380
402
|
# q = Depq.new
|
@@ -395,6 +417,15 @@ class Depq
|
|
395
417
|
# p q.delete_min #=> "bar"
|
396
418
|
# p q.delete_min #=> "Foo"
|
397
419
|
#
|
420
|
+
# class Cmp
|
421
|
+
# def call(a,b) a.casecmp(b) end
|
422
|
+
# end
|
423
|
+
# q = Depq.new(Cmp.new)
|
424
|
+
# q.insert "Foo"
|
425
|
+
# q.insert "bar"
|
426
|
+
# p q.delete_min #=> "bar"
|
427
|
+
# p q.delete_min #=> "Foo"
|
428
|
+
#
|
398
429
|
def initialize(cmp = :<=>)
|
399
430
|
@cmp = cmp
|
400
431
|
@ary = []
|
@@ -442,45 +473,50 @@ class Depq
|
|
442
473
|
end
|
443
474
|
private :each_entry
|
444
475
|
|
476
|
+
def mode_call(name, *args)
|
477
|
+
send(Mode[@mode][name], *args)
|
478
|
+
end
|
479
|
+
private :mode_call
|
480
|
+
|
445
481
|
def use_min
|
446
|
-
if @mode ==
|
482
|
+
if @mode == :min || @mode == :interval
|
447
483
|
if @heapsize < self.size
|
448
|
-
@heapsize =
|
484
|
+
@heapsize = mode_call(:heapify, @heapsize)
|
449
485
|
end
|
450
486
|
else
|
451
|
-
@mode =
|
452
|
-
@heapsize =
|
487
|
+
@mode = :min
|
488
|
+
@heapsize = mode_call(:heapify)
|
453
489
|
end
|
454
490
|
end
|
455
491
|
private :use_min
|
456
492
|
|
457
493
|
def use_max
|
458
|
-
if @mode ==
|
494
|
+
if @mode == :max || @mode == :interval
|
459
495
|
if @heapsize < self.size
|
460
|
-
@heapsize =
|
496
|
+
@heapsize = mode_call(:heapify, @heapsize)
|
461
497
|
end
|
462
498
|
else
|
463
|
-
@mode =
|
464
|
-
@heapsize =
|
499
|
+
@mode = :max
|
500
|
+
@heapsize = mode_call(:heapify)
|
465
501
|
end
|
466
502
|
end
|
467
503
|
private :use_max
|
468
504
|
|
469
505
|
def use_minmax
|
470
|
-
if @mode ==
|
506
|
+
if @mode == :interval
|
471
507
|
if @heapsize < self.size
|
472
|
-
@heapsize =
|
508
|
+
@heapsize = mode_call(:heapify, @heapsize)
|
473
509
|
end
|
474
510
|
else
|
475
|
-
@mode =
|
476
|
-
@heapsize =
|
511
|
+
@mode = :interval
|
512
|
+
@heapsize = mode_call(:heapify)
|
477
513
|
end
|
478
514
|
end
|
479
515
|
private :use_minmax
|
480
516
|
|
481
517
|
def mode_heapify
|
482
518
|
if @mode
|
483
|
-
@heapsize =
|
519
|
+
@heapsize = mode_call(:heapify)
|
484
520
|
end
|
485
521
|
end
|
486
522
|
private :mode_heapify
|
@@ -499,18 +535,6 @@ class Depq
|
|
499
535
|
end
|
500
536
|
private :default_subpriority
|
501
537
|
|
502
|
-
def compare_for_min(priority1, subpriority1, priority2, subpriority2)
|
503
|
-
compare_priority(priority1, priority2).nonzero? or
|
504
|
-
(subpriority1 <=> subpriority2)
|
505
|
-
end
|
506
|
-
private :compare_for_min
|
507
|
-
|
508
|
-
def compare_for_max(priority1, subpriority1, priority2, subpriority2)
|
509
|
-
compare_priority(priority1, priority2).nonzero? or
|
510
|
-
(subpriority2 <=> subpriority1)
|
511
|
-
end
|
512
|
-
private :compare_for_max
|
513
|
-
|
514
538
|
def initialize_copy(obj) # :nodoc:
|
515
539
|
if defined? @ary
|
516
540
|
@ary = @ary.dup
|
@@ -562,6 +586,9 @@ class Depq
|
|
562
586
|
# p q.compare_priority("a", "a") #=> 0
|
563
587
|
# p q.compare_priority("b", "a") #=> 1
|
564
588
|
#
|
589
|
+
# q = Depq.new(:casecmp)
|
590
|
+
# p q.compare_priority("a", "A") #=> 0
|
591
|
+
#
|
565
592
|
def compare_priority(priority1, priority2)
|
566
593
|
if @cmp.kind_of? Symbol
|
567
594
|
priority1.__send__(@cmp, priority2)
|
@@ -661,7 +688,7 @@ class Depq
|
|
661
688
|
set_entry(loc.send(:index), loc, priority, subpriority)
|
662
689
|
else
|
663
690
|
mode_heapify
|
664
|
-
|
691
|
+
mode_call(:update_prio, loc, priority, subpriority)
|
665
692
|
end
|
666
693
|
end
|
667
694
|
private :internal_set_priority
|
@@ -735,7 +762,7 @@ class Depq
|
|
735
762
|
|
736
763
|
# insert all values in iter.
|
737
764
|
#
|
738
|
-
# The argument, iter, should have each method.
|
765
|
+
# The argument, iter, should have +each+ method.
|
739
766
|
#
|
740
767
|
# This method returns nil.
|
741
768
|
#
|
@@ -758,17 +785,20 @@ class Depq
|
|
758
785
|
#
|
759
786
|
# This method doesn't delete the element from the queue.
|
760
787
|
#
|
761
|
-
# q = Depq.new
|
762
|
-
# p q.find_min_locator #=> nil
|
763
|
-
# q.insert 3
|
764
|
-
# q.insert 1
|
765
|
-
# q.insert 2
|
788
|
+
# q = Depq.new
|
789
|
+
# p q.find_min_locator #=> nil
|
790
|
+
# q.insert 3
|
791
|
+
# q.insert 1
|
792
|
+
# q.insert 2
|
793
|
+
# p q.find_min_locator #=> #<Depq::Locator: 1>
|
766
794
|
# p q.find_min_locator #=> #<Depq::Locator: 1>
|
795
|
+
# p q.delete_min #=> 1
|
796
|
+
# p q.find_min_locator #=> #<Depq::Locator: 2>
|
767
797
|
#
|
768
798
|
def find_min_locator
|
769
799
|
return nil if empty?
|
770
800
|
use_min
|
771
|
-
|
801
|
+
mode_call(:find_min_loc)
|
772
802
|
end
|
773
803
|
|
774
804
|
# return the minimum value with its priority.
|
@@ -782,6 +812,9 @@ class Depq
|
|
782
812
|
# q.insert "banana", 3
|
783
813
|
# q.insert "melon", 2
|
784
814
|
# p q.find_min_priority #=> ["durian", 1]
|
815
|
+
# p q.find_min_priority #=> ["durian", 1]
|
816
|
+
# p q.delete_min #=> "durian"
|
817
|
+
# p q.find_min_priority #=> ["melon", 2]
|
785
818
|
# q.clear
|
786
819
|
# p q.find_min_priority #=> nil
|
787
820
|
#
|
@@ -794,12 +827,15 @@ class Depq
|
|
794
827
|
#
|
795
828
|
# This method doesn't delete the element from the queue.
|
796
829
|
#
|
797
|
-
# q = Depq.new
|
798
|
-
# p q.find_min #=> nil
|
799
|
-
# q.insert 3
|
800
|
-
# q.insert 1
|
801
|
-
# q.insert 2
|
830
|
+
# q = Depq.new
|
831
|
+
# p q.find_min #=> nil
|
832
|
+
# q.insert 3
|
833
|
+
# q.insert 1
|
834
|
+
# q.insert 2
|
835
|
+
# p q.find_min #=> 1
|
802
836
|
# p q.find_min #=> 1
|
837
|
+
# p q.delete_min #=> 1
|
838
|
+
# p q.find_min #=> 2
|
803
839
|
#
|
804
840
|
def find_min
|
805
841
|
loc = find_min_locator and loc.value
|
@@ -818,11 +854,15 @@ class Depq
|
|
818
854
|
# q.insert 1
|
819
855
|
# q.insert 2
|
820
856
|
# p q.find_max_locator #=> #<Depq::Locator: 3>
|
857
|
+
# p q.find_max_locator #=> #<Depq::Locator: 3>
|
858
|
+
# p q.find_max_locator #=> #<Depq::Locator: 3>
|
859
|
+
# p q.delete_max #=> 3
|
860
|
+
# p q.find_max_locator #=> #<Depq::Locator: 2>
|
821
861
|
#
|
822
862
|
def find_max_locator
|
823
863
|
return nil if empty?
|
824
864
|
use_max
|
825
|
-
|
865
|
+
mode_call(:find_max_loc)
|
826
866
|
end
|
827
867
|
|
828
868
|
# return the maximum value with its priority.
|
@@ -836,6 +876,9 @@ class Depq
|
|
836
876
|
# q.insert "banana", 3
|
837
877
|
# q.insert "melon", 2
|
838
878
|
# p q.find_max_priority #=> ["banana", 3]
|
879
|
+
# p q.find_max_priority #=> ["banana", 3]
|
880
|
+
# p q.delete_max #=> "banana"
|
881
|
+
# p q.find_max_priority #=> ["melon", 2]
|
839
882
|
# q.clear
|
840
883
|
# p q.find_max_priority #=> nil
|
841
884
|
#
|
@@ -854,6 +897,9 @@ class Depq
|
|
854
897
|
# q.insert 1
|
855
898
|
# q.insert 2
|
856
899
|
# p q.find_max #=> 3
|
900
|
+
# p q.find_max #=> 3
|
901
|
+
# p q.delete_max #=> 3
|
902
|
+
# p q.find_max #=> 2
|
857
903
|
#
|
858
904
|
def find_max
|
859
905
|
loc = find_max_locator and loc.value
|
@@ -874,7 +920,7 @@ class Depq
|
|
874
920
|
def find_minmax_locator
|
875
921
|
return [nil, nil] if empty?
|
876
922
|
use_minmax
|
877
|
-
return
|
923
|
+
return mode_call(:find_minmax_loc)
|
878
924
|
end
|
879
925
|
|
880
926
|
# returns the minimum and maximum value as a two-element array.
|
@@ -916,7 +962,7 @@ class Depq
|
|
916
962
|
loc
|
917
963
|
else
|
918
964
|
mode_heapify
|
919
|
-
@heapsize =
|
965
|
+
@heapsize = mode_call(:delete_loc, loc)
|
920
966
|
loc
|
921
967
|
end
|
922
968
|
end
|
@@ -938,8 +984,8 @@ class Depq
|
|
938
984
|
def delete_min_locator
|
939
985
|
return nil if empty?
|
940
986
|
use_min
|
941
|
-
loc =
|
942
|
-
@heapsize =
|
987
|
+
loc = mode_call(:find_min_loc)
|
988
|
+
@heapsize = mode_call(:delete_loc, loc)
|
943
989
|
loc
|
944
990
|
end
|
945
991
|
|
@@ -1003,8 +1049,8 @@ class Depq
|
|
1003
1049
|
def delete_max_locator
|
1004
1050
|
return nil if empty?
|
1005
1051
|
use_max
|
1006
|
-
loc =
|
1007
|
-
@heapsize =
|
1052
|
+
loc = mode_call(:find_max_loc)
|
1053
|
+
@heapsize = mode_call(:delete_loc, loc)
|
1008
1054
|
loc
|
1009
1055
|
end
|
1010
1056
|
|
@@ -1113,6 +1159,62 @@ class Depq
|
|
1113
1159
|
loc.value
|
1114
1160
|
end
|
1115
1161
|
|
1162
|
+
# replaces the minimum element.
|
1163
|
+
#
|
1164
|
+
# If _priority_ is not given, _value_ is used.
|
1165
|
+
#
|
1166
|
+
# If _subpriority_ is not given or nil, totalcount is used.
|
1167
|
+
#
|
1168
|
+
# This is virtually same as delete_min and insert except the locator is reused.
|
1169
|
+
# This method increment totalcount.
|
1170
|
+
#
|
1171
|
+
# q = Depq.new
|
1172
|
+
# q.insert 2
|
1173
|
+
# q.insert 4
|
1174
|
+
# q.insert 3
|
1175
|
+
# p q.min #=> 2
|
1176
|
+
# q.replace_min(5)
|
1177
|
+
# p q.delete_min #=> 3
|
1178
|
+
# p q.delete_min #=> 4
|
1179
|
+
# p q.delete_min #=> 5
|
1180
|
+
# p q.delete_min #=> nil
|
1181
|
+
#
|
1182
|
+
def replace_min(value, priority=value, subpriority=nil)
|
1183
|
+
subpriority ||= @totalcount
|
1184
|
+
@totalcount += 1
|
1185
|
+
loc = find_min_locator
|
1186
|
+
loc.update(value, priority, subpriority)
|
1187
|
+
loc
|
1188
|
+
end
|
1189
|
+
|
1190
|
+
# replaces the maximum element.
|
1191
|
+
#
|
1192
|
+
# If _priority_ is not given, _value_ is used.
|
1193
|
+
#
|
1194
|
+
# If _subpriority_ is not given or nil, totalcount is used.
|
1195
|
+
#
|
1196
|
+
# This is virtually same as delete_max and insert except the locator is reused.
|
1197
|
+
# This method increment totalcount.
|
1198
|
+
#
|
1199
|
+
# q = Depq.new
|
1200
|
+
# q.insert 1
|
1201
|
+
# q.insert 4
|
1202
|
+
# q.insert 3
|
1203
|
+
# p q.max #=> 4
|
1204
|
+
# q.replace_max(2)
|
1205
|
+
# p q.delete_max #=> 3
|
1206
|
+
# p q.delete_max #=> 2
|
1207
|
+
# p q.delete_max #=> 1
|
1208
|
+
# p q.delete_max #=> nil
|
1209
|
+
#
|
1210
|
+
def replace_max(value, priority=value, subpriority=nil)
|
1211
|
+
subpriority ||= @totalcount
|
1212
|
+
@totalcount += 1
|
1213
|
+
loc = find_max_locator
|
1214
|
+
loc.update(value, priority, subpriority)
|
1215
|
+
loc
|
1216
|
+
end
|
1217
|
+
|
1116
1218
|
# iterate over the locators in the queue.
|
1117
1219
|
#
|
1118
1220
|
# The iteration order is unspecified.
|
@@ -1302,504 +1404,519 @@ class Depq
|
|
1302
1404
|
end
|
1303
1405
|
end
|
1304
1406
|
|
1407
|
+
private
|
1305
1408
|
# :stopdoc:
|
1306
1409
|
|
1307
|
-
|
1308
|
-
def size(ary)
|
1309
|
-
return ary.size / ARY_SLICE_SIZE
|
1310
|
-
end
|
1311
|
-
|
1312
|
-
def get_entry(ary, i)
|
1313
|
-
locator = ary[i*ARY_SLICE_SIZE+0]
|
1314
|
-
priority = ary[i*ARY_SLICE_SIZE+1]
|
1315
|
-
subpriority = ary[i*ARY_SLICE_SIZE+2]
|
1316
|
-
[locator, priority, subpriority]
|
1317
|
-
end
|
1410
|
+
## utilities for heap implementation
|
1318
1411
|
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1412
|
+
def swap(i, j)
|
1413
|
+
ei, pi, si = get_entry(i)
|
1414
|
+
ej, pj, sj = get_entry(j)
|
1415
|
+
set_entry(i, ej, pj, sj)
|
1416
|
+
set_entry(j, ei, pi, si)
|
1417
|
+
ei.send(:index=, j)
|
1418
|
+
ej.send(:index=, i)
|
1419
|
+
end
|
1326
1420
|
|
1327
|
-
|
1328
|
-
locator, priority, subpriority = ary[i*ARY_SLICE_SIZE, ARY_SLICE_SIZE]
|
1329
|
-
ary[i*ARY_SLICE_SIZE, ARY_SLICE_SIZE] = []
|
1330
|
-
[locator, priority, subpriority]
|
1331
|
-
end
|
1421
|
+
## common part of min-heap and max-heap
|
1332
1422
|
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1423
|
+
def mm_upheap(j, upper)
|
1424
|
+
while true
|
1425
|
+
return if j <= 0
|
1426
|
+
i = (j-1) >> 1
|
1427
|
+
return if upper.call(i, j)
|
1428
|
+
swap(j, i)
|
1429
|
+
j = i
|
1340
1430
|
end
|
1341
1431
|
end
|
1342
1432
|
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1433
|
+
def mm_downheap(i, upper)
|
1434
|
+
while true
|
1435
|
+
j = i*2+1
|
1436
|
+
k = i*2+2
|
1437
|
+
return if self.size <= j
|
1438
|
+
if self.size == k
|
1439
|
+
return if upper.call(i, j)
|
1440
|
+
swap(i, j)
|
1441
|
+
i = j
|
1442
|
+
else
|
1443
|
+
return if upper.call(i, j) && upper.call(i, k)
|
1444
|
+
loc = upper.call(j, k) ? j : k
|
1445
|
+
swap(i, loc)
|
1446
|
+
i = loc
|
1353
1447
|
end
|
1354
1448
|
end
|
1449
|
+
end
|
1355
1450
|
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
return if size(ary) <= j
|
1361
|
-
if size(ary) == k
|
1362
|
-
return if upper?(q, ary, i, j)
|
1363
|
-
swap(ary, i, j)
|
1364
|
-
i = j
|
1365
|
-
else
|
1366
|
-
return if upper?(q, ary, i, j) && upper?(q, ary, i, k)
|
1367
|
-
loc = upper?(q, ary, j, k) ? j : k
|
1368
|
-
swap(ary, i, loc)
|
1369
|
-
i = loc
|
1370
|
-
end
|
1371
|
-
end
|
1372
|
-
end
|
1451
|
+
def mm_find_top_loc
|
1452
|
+
loc, _ = get_entry(0)
|
1453
|
+
loc
|
1454
|
+
end
|
1373
1455
|
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1456
|
+
def mm_delete_loc(loc, upper)
|
1457
|
+
i = loc.send(:index)
|
1458
|
+
_, priority, subpriority = get_entry(i)
|
1459
|
+
last = self.size - 1
|
1460
|
+
loc.send(:internal_deleted, priority, subpriority)
|
1461
|
+
el, pl, sl = delete_entry(last)
|
1462
|
+
if i != last
|
1463
|
+
set_entry(i, el, pl, sl)
|
1464
|
+
el.send(:index=, i)
|
1465
|
+
mm_downheap(i, upper)
|
1377
1466
|
end
|
1467
|
+
self.size
|
1468
|
+
end
|
1378
1469
|
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1470
|
+
def mm_heapify(heapsize, upper)
|
1471
|
+
# compare number of data movements in worst case.
|
1472
|
+
# choose a way for less data movements.
|
1473
|
+
#
|
1474
|
+
# current size = ary.size / ARY_SLICE_SIZE = n
|
1475
|
+
# addition size = n - heapsize = m
|
1476
|
+
# heap tree height = Math.log2(n+1) = h
|
1477
|
+
#
|
1478
|
+
# worst data movements using mm_downheap:
|
1479
|
+
# - bottom elements cannot move.
|
1480
|
+
# - elements above can move 1 time.
|
1481
|
+
# - ...
|
1482
|
+
# - top element can move h-1 times.
|
1483
|
+
#
|
1484
|
+
# 1*2**(h-2) + 2*2**(h-3) + 3*2**(h-4) + ... + (h-1)*2**0
|
1485
|
+
# = sum i*2**(h-1-i), i=1 to h-1
|
1486
|
+
# = 2**h - h - 1
|
1487
|
+
# = n - h
|
1488
|
+
#
|
1489
|
+
# worst data movements using mm_upheap
|
1490
|
+
# - bottom elements can move h-1 times.
|
1491
|
+
# - n/2 elements are placed at bottom.
|
1492
|
+
# - approximate all elements are at bottom...
|
1493
|
+
#
|
1494
|
+
# (h-1) * m
|
1495
|
+
#
|
1496
|
+
# condition to use mm_downheap:
|
1497
|
+
#
|
1498
|
+
# n - h < (h-1) * m
|
1499
|
+
# n - 1 < (h-1) * (m+1)
|
1500
|
+
#
|
1501
|
+
currentsize = self.size
|
1502
|
+
h = Math.log(currentsize+1)/Math.log(2)
|
1503
|
+
if currentsize - 1 < (h - 1) * (currentsize - heapsize + 1)
|
1504
|
+
n = (currentsize - 2) / 2
|
1505
|
+
n.downto(0) {|i|
|
1506
|
+
mm_downheap(i, upper)
|
1507
|
+
}
|
1508
|
+
else
|
1509
|
+
heapsize.upto(currentsize-1) {|i|
|
1510
|
+
mm_upheap(i, upper)
|
1511
|
+
}
|
1391
1512
|
end
|
1513
|
+
currentsize
|
1514
|
+
end
|
1392
1515
|
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
1398
|
-
# addition size = n - heapsize = m
|
1399
|
-
# heap tree height = Math.log2(n+1) = h
|
1400
|
-
#
|
1401
|
-
# worst data movements using downheap:
|
1402
|
-
# - bottom elements cannot move.
|
1403
|
-
# - elements above can move 1 time.
|
1404
|
-
# - ...
|
1405
|
-
# - top element can move h-1 times.
|
1406
|
-
#
|
1407
|
-
# 1*2**(h-2) + 2*2**(h-3) + 3*2**(h-4) + ... + (h-1)*2**0
|
1408
|
-
# = sum i*2**(h-1-i), i=1 to h-1
|
1409
|
-
# = 2**h - h - 1
|
1410
|
-
# = n - h
|
1411
|
-
#
|
1412
|
-
# worst data movements using upheap
|
1413
|
-
# - bottom elements can move h-1 times.
|
1414
|
-
# - n/2 elements are placed at bottom.
|
1415
|
-
# - approximate all elements are at bottom...
|
1416
|
-
#
|
1417
|
-
# (h-1) * m
|
1418
|
-
#
|
1419
|
-
# condition to use downheap:
|
1420
|
-
#
|
1421
|
-
# n - h < (h-1) * m
|
1422
|
-
# n - 1 < (h-1) * (m+1)
|
1423
|
-
#
|
1424
|
-
currentsize = size(ary)
|
1425
|
-
h = Math.log(currentsize+1)/Math.log(2)
|
1426
|
-
if currentsize - 1 < (h - 1) * (currentsize - heapsize + 1)
|
1427
|
-
n = (currentsize - 2) / 2
|
1428
|
-
n.downto(0) {|i|
|
1429
|
-
downheap(q, ary, i)
|
1430
|
-
}
|
1431
|
-
else
|
1432
|
-
heapsize.upto(currentsize-1) {|i|
|
1433
|
-
upheap(q, ary, i)
|
1434
|
-
}
|
1435
|
-
end
|
1436
|
-
currentsize
|
1437
|
-
end
|
1516
|
+
## min-heap implementation
|
1517
|
+
|
1518
|
+
def min_compare(priority1, subpriority1, priority2, subpriority2)
|
1519
|
+
compare_priority(priority1, priority2).nonzero? or
|
1520
|
+
(subpriority1 <=> subpriority2)
|
1438
1521
|
end
|
1439
1522
|
|
1440
|
-
|
1523
|
+
def min_upper?(i, j)
|
1524
|
+
ei, pi, si = get_entry(i)
|
1525
|
+
ej, pj, sj = get_entry(j)
|
1526
|
+
min_compare(pi, si, pj, sj) <= 0
|
1441
1527
|
end
|
1442
|
-
class << MinHeap
|
1443
|
-
include SimpleHeap
|
1444
1528
|
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1529
|
+
def min_update_prio(loc, priority, subpriority)
|
1530
|
+
i = loc.send(:index)
|
1531
|
+
ei, pi, si = get_entry(i)
|
1532
|
+
set_entry(i, ei, priority, subpriority)
|
1533
|
+
cmp = min_compare(pi, si, priority, subpriority)
|
1534
|
+
if cmp < 0
|
1535
|
+
# loc.priority < priority
|
1536
|
+
mm_downheap(i, method(:min_upper?))
|
1537
|
+
elsif cmp > 0
|
1538
|
+
# loc.priority > priority
|
1539
|
+
mm_upheap(i, method(:min_upper?))
|
1449
1540
|
end
|
1541
|
+
end
|
1450
1542
|
|
1451
|
-
|
1452
|
-
|
1453
|
-
|
1454
|
-
cmp = q.send(:compare_for_min, pi, si, priority, subpriority)
|
1455
|
-
set_entry(ary, i, ei, priority, subpriority)
|
1456
|
-
if cmp < 0
|
1457
|
-
# loc.priority < priority
|
1458
|
-
downheap(q, ary, i)
|
1459
|
-
elsif cmp > 0
|
1460
|
-
# loc.priority > priority
|
1461
|
-
upheap(q, ary, i)
|
1462
|
-
end
|
1463
|
-
end
|
1543
|
+
def min_delete_loc(loc)
|
1544
|
+
mm_delete_loc loc, method(:min_upper?)
|
1545
|
+
end
|
1464
1546
|
|
1465
|
-
|
1547
|
+
def min_heapify(heapsize=0)
|
1548
|
+
mm_heapify heapsize, method(:min_upper?)
|
1466
1549
|
end
|
1467
1550
|
|
1468
|
-
|
1551
|
+
alias min_find_min_loc mm_find_top_loc
|
1552
|
+
|
1553
|
+
MinMode = {
|
1554
|
+
:update_prio => :min_update_prio,
|
1555
|
+
:delete_loc => :min_delete_loc,
|
1556
|
+
:heapify => :min_heapify,
|
1557
|
+
:find_min_loc => :min_find_min_loc
|
1558
|
+
}
|
1559
|
+
|
1560
|
+
## max-heap implementation
|
1561
|
+
|
1562
|
+
def max_compare(priority1, subpriority1, priority2, subpriority2)
|
1563
|
+
compare_priority(priority1, priority2).nonzero? or
|
1564
|
+
(subpriority2 <=> subpriority1)
|
1469
1565
|
end
|
1470
|
-
class << MaxHeap
|
1471
|
-
include SimpleHeap
|
1472
1566
|
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1567
|
+
def max_upper?(i, j)
|
1568
|
+
ei, pi, si = get_entry(i)
|
1569
|
+
ej, pj, sj = get_entry(j)
|
1570
|
+
max_compare(pi, si, pj, sj) >= 0
|
1571
|
+
end
|
1478
1572
|
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
downheap(q, ary, i)
|
1491
|
-
end
|
1573
|
+
def max_update_prio(loc, priority, subpriority)
|
1574
|
+
i = loc.send(:index)
|
1575
|
+
ei, pi, si = get_entry(i)
|
1576
|
+
set_entry(i, ei, priority, subpriority)
|
1577
|
+
cmp = max_compare(pi, si, priority, subpriority)
|
1578
|
+
if cmp < 0
|
1579
|
+
# loc.priority < priority
|
1580
|
+
mm_upheap(i, method(:max_upper?))
|
1581
|
+
elsif cmp > 0
|
1582
|
+
# loc.priority > priority
|
1583
|
+
mm_downheap(i, method(:max_upper?))
|
1492
1584
|
end
|
1493
|
-
|
1494
|
-
alias find_max_loc find_top_loc
|
1495
1585
|
end
|
1496
1586
|
|
1497
|
-
|
1587
|
+
def max_delete_loc(loc)
|
1588
|
+
mm_delete_loc loc, method(:max_upper?)
|
1498
1589
|
end
|
1499
|
-
class << IntervalHeap
|
1500
|
-
include HeapArray
|
1501
1590
|
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
def minside(i) i & ~1 end
|
1506
|
-
def maxside(i) i | 1 end
|
1507
|
-
def parent_minside(j) (j-2)/2 & ~1 end
|
1508
|
-
def parent_maxside(j) (j-2)/2 | 1 end
|
1509
|
-
def child1_minside(i) i &= ~1; (i*2+2) & ~1 end
|
1510
|
-
def child1_maxside(i) i &= ~1; (i*2+2) | 1 end
|
1511
|
-
def child2_minside(i) i &= ~1; (i*2+4) & ~1 end
|
1512
|
-
def child2_maxside(i) i &= ~1; (i*2+4) | 1 end
|
1591
|
+
def max_heapify(heapsize=0)
|
1592
|
+
mm_heapify heapsize, method(:max_upper?)
|
1593
|
+
end
|
1513
1594
|
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1595
|
+
alias max_find_max_loc mm_find_top_loc
|
1596
|
+
|
1597
|
+
MaxMode = {
|
1598
|
+
:update_prio => :max_update_prio,
|
1599
|
+
:delete_loc => :max_delete_loc,
|
1600
|
+
:heapify => :max_heapify,
|
1601
|
+
:find_max_loc => :max_find_max_loc
|
1602
|
+
}
|
1603
|
+
|
1604
|
+
## interval-heap implementation
|
1605
|
+
|
1606
|
+
def itv_root?(i) i < 2 end
|
1607
|
+
def itv_minside?(i) i.even? end
|
1608
|
+
def itv_maxside?(i) i.odd? end
|
1609
|
+
def itv_minside(i) i & ~1 end
|
1610
|
+
def itv_maxside(i) i | 1 end
|
1611
|
+
def itv_parent_minside(j) (j-2)/2 & ~1 end
|
1612
|
+
def itv_parent_maxside(j) (j-2)/2 | 1 end
|
1613
|
+
def itv_child1_minside(i) i &= ~1; (i*2+2) & ~1 end
|
1614
|
+
def itv_child1_maxside(i) i &= ~1; (i*2+2) | 1 end
|
1615
|
+
def itv_child2_minside(i) i &= ~1; (i*2+4) & ~1 end
|
1616
|
+
def itv_child2_maxside(i) i &= ~1; (i*2+4) | 1 end
|
1617
|
+
|
1618
|
+
def pcmp(i, j)
|
1619
|
+
ei, pi, si = get_entry(i)
|
1620
|
+
ej, pj, sj = get_entry(j)
|
1621
|
+
compare_priority(pi, pj)
|
1622
|
+
end
|
1519
1623
|
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1624
|
+
def scmp(i, j)
|
1625
|
+
ei, pi, si = get_entry(i)
|
1626
|
+
ej, pj, sj = get_entry(j)
|
1627
|
+
si <=> sj
|
1628
|
+
end
|
1525
1629
|
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1630
|
+
def itv_psame(i)
|
1631
|
+
pcmp(itv_minside(i), itv_maxside(i)) == 0
|
1632
|
+
end
|
1529
1633
|
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
end
|
1634
|
+
def itv_travel(i, range, fix_subpriority)
|
1635
|
+
while true
|
1636
|
+
j = yield i
|
1637
|
+
return i if !j
|
1638
|
+
swap i, j
|
1639
|
+
if fix_subpriority
|
1640
|
+
imin = itv_minside(i)
|
1641
|
+
imax = itv_maxside(i)
|
1642
|
+
if range.include?(imin) && range.include?(imax)
|
1643
|
+
if pcmp(imin, imax) == 0 && scmp(imin, imax) > 0
|
1644
|
+
swap imin, imax
|
1542
1645
|
end
|
1543
1646
|
end
|
1544
|
-
i = j
|
1545
1647
|
end
|
1648
|
+
i = j
|
1546
1649
|
end
|
1650
|
+
end
|
1547
1651
|
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1652
|
+
def itv_upheap_minside(i, range)
|
1653
|
+
itv_travel(i, range, true) {|j|
|
1654
|
+
if itv_root?(j)
|
1655
|
+
nil
|
1656
|
+
elsif !range.include?(k = itv_parent_minside(j))
|
1657
|
+
nil
|
1658
|
+
else
|
1659
|
+
if pcmp(k, j) > 0
|
1660
|
+
swap(itv_minside(k), itv_maxside(k)) if itv_psame(k)
|
1661
|
+
k
|
1554
1662
|
else
|
1555
|
-
|
1556
|
-
swap(ary, minside(k), maxside(k)) if psame(q, ary, k)
|
1557
|
-
k
|
1558
|
-
else
|
1559
|
-
nil
|
1560
|
-
end
|
1663
|
+
nil
|
1561
1664
|
end
|
1562
|
-
|
1563
|
-
|
1665
|
+
end
|
1666
|
+
}
|
1667
|
+
end
|
1564
1668
|
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1669
|
+
def itv_upheap_maxside(i, range)
|
1670
|
+
itv_travel(i, range, true) {|j|
|
1671
|
+
if itv_root?(j)
|
1672
|
+
nil
|
1673
|
+
elsif !range.include?(k = itv_parent_maxside(j))
|
1674
|
+
nil
|
1675
|
+
else
|
1676
|
+
if pcmp(k, j) < 0
|
1677
|
+
k
|
1571
1678
|
else
|
1572
|
-
|
1573
|
-
k
|
1574
|
-
else
|
1575
|
-
nil
|
1576
|
-
end
|
1679
|
+
nil
|
1577
1680
|
end
|
1578
|
-
|
1579
|
-
|
1681
|
+
end
|
1682
|
+
}
|
1683
|
+
end
|
1580
1684
|
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1685
|
+
def itv_downheap_minside(i, range)
|
1686
|
+
itv_travel(i, range, true) {|j|
|
1687
|
+
k1 = itv_child1_minside(j)
|
1688
|
+
k2 = itv_child2_minside(j)
|
1689
|
+
if !range.include?(k1)
|
1690
|
+
nil
|
1691
|
+
else
|
1692
|
+
if !range.include?(k2)
|
1693
|
+
k = k1
|
1587
1694
|
else
|
1588
|
-
if
|
1695
|
+
if (pc = pcmp(k1, k2)) < 0
|
1696
|
+
k = k1
|
1697
|
+
elsif pc > 0
|
1698
|
+
k = k2
|
1699
|
+
elsif (sc = scmp(k1, k2)) <= 0
|
1589
1700
|
k = k1
|
1590
1701
|
else
|
1591
|
-
|
1592
|
-
k = k1
|
1593
|
-
elsif pc > 0
|
1594
|
-
k = k2
|
1595
|
-
elsif (sc = scmp(q, ary, k1, k2)) <= 0
|
1596
|
-
k = k1
|
1597
|
-
else
|
1598
|
-
k = k2
|
1599
|
-
end
|
1600
|
-
end
|
1601
|
-
if (pc = pcmp(q, ary, k, j)) < 0
|
1602
|
-
k
|
1603
|
-
else
|
1604
|
-
nil
|
1702
|
+
k = k2
|
1605
1703
|
end
|
1606
1704
|
end
|
1607
|
-
|
1608
|
-
|
1609
|
-
|
1610
|
-
def downheap_maxside(q, ary, i, range)
|
1611
|
-
travel(q, ary, i, range, true) {|j|
|
1612
|
-
k1 = child1_maxside(j)
|
1613
|
-
k2 = child2_maxside(j)
|
1614
|
-
k1 = minside(k1) if range.include?(k1) && psame(q, ary, k1)
|
1615
|
-
k2 = minside(k2) if range.include?(k2) && psame(q, ary, k2)
|
1616
|
-
if !range.include?(k1)
|
1617
|
-
nil
|
1705
|
+
if (pc = pcmp(k, j)) < 0
|
1706
|
+
k
|
1618
1707
|
else
|
1619
|
-
|
1620
|
-
k = k1
|
1621
|
-
else
|
1622
|
-
if (pc = pcmp(q, ary, k1, k2)) < 0
|
1623
|
-
k = k2
|
1624
|
-
elsif pc > 0
|
1625
|
-
k = k1
|
1626
|
-
elsif (sc = scmp(q, ary, k1, k2)) <= 0
|
1627
|
-
k = k1
|
1628
|
-
else
|
1629
|
-
k = k2
|
1630
|
-
end
|
1631
|
-
end
|
1632
|
-
if (pc = pcmp(q, ary, k, j)) > 0
|
1633
|
-
swap(ary, minside(k), maxside(k)) if minside?(k)
|
1634
|
-
maxside(k)
|
1635
|
-
else
|
1636
|
-
nil
|
1637
|
-
end
|
1708
|
+
nil
|
1638
1709
|
end
|
1639
|
-
|
1640
|
-
|
1710
|
+
end
|
1711
|
+
}
|
1712
|
+
end
|
1641
1713
|
|
1642
|
-
|
1643
|
-
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
|
1648
|
-
|
1649
|
-
|
1650
|
-
|
1714
|
+
def itv_downheap_maxside(i, range)
|
1715
|
+
itv_travel(i, range, true) {|j|
|
1716
|
+
k1 = itv_child1_maxside(j)
|
1717
|
+
k2 = itv_child2_maxside(j)
|
1718
|
+
k1 = itv_minside(k1) if range.include?(k1) && itv_psame(k1)
|
1719
|
+
k2 = itv_minside(k2) if range.include?(k2) && itv_psame(k2)
|
1720
|
+
if !range.include?(k1)
|
1721
|
+
nil
|
1722
|
+
else
|
1723
|
+
if !range.include?(k2)
|
1724
|
+
k = k1
|
1651
1725
|
else
|
1652
|
-
if
|
1653
|
-
k =
|
1654
|
-
elsif
|
1655
|
-
k =
|
1726
|
+
if (pc = pcmp(k1, k2)) < 0
|
1727
|
+
k = k2
|
1728
|
+
elsif pc > 0
|
1729
|
+
k = k1
|
1730
|
+
elsif (sc = scmp(k1, k2)) <= 0
|
1731
|
+
k = k1
|
1732
|
+
else
|
1733
|
+
k = k2
|
1656
1734
|
end
|
1657
1735
|
end
|
1658
|
-
if
|
1659
|
-
|
1660
|
-
|
1661
|
-
k
|
1736
|
+
if (pc = pcmp(k, j)) > 0
|
1737
|
+
swap(itv_minside(k), itv_maxside(k)) if itv_minside?(k)
|
1738
|
+
itv_maxside(k)
|
1662
1739
|
else
|
1663
1740
|
nil
|
1664
1741
|
end
|
1665
|
-
|
1666
|
-
|
1742
|
+
end
|
1743
|
+
}
|
1744
|
+
end
|
1667
1745
|
|
1668
|
-
|
1669
|
-
|
1670
|
-
|
1671
|
-
|
1672
|
-
|
1673
|
-
|
1674
|
-
|
1675
|
-
|
1676
|
-
k2 = kk if range.include?(kk=child2_minside(j)) && pcmp(q, ary, j, kk) == 0
|
1677
|
-
end
|
1678
|
-
else
|
1679
|
-
if range.include?(kk=child1_minside(j)) && pcmp(q, ary, j, kk) == 0
|
1680
|
-
k1 = kk
|
1681
|
-
elsif range.include?(kk=child1_maxside(j)) && pcmp(q, ary, j, kk) == 0
|
1682
|
-
k1 = kk
|
1683
|
-
end
|
1684
|
-
if range.include?(kk=child2_minside(j)) && pcmp(q, ary, j, kk) == 0
|
1685
|
-
k2 = kk
|
1686
|
-
elsif range.include?(kk=child2_maxside(j)) && pcmp(q, ary, j, kk) == 0
|
1687
|
-
k2 = kk
|
1688
|
-
end
|
1746
|
+
def itv_upheap_sub(i, range)
|
1747
|
+
itv_travel(i, range, false) {|j|
|
1748
|
+
k = nil
|
1749
|
+
if itv_minside?(j)
|
1750
|
+
if range.include?(kk=itv_parent_maxside(j)) && pcmp(j, kk) == 0
|
1751
|
+
k = kk
|
1752
|
+
elsif range.include?(kk=itv_parent_minside(j)) && pcmp(j, kk) == 0
|
1753
|
+
k = kk
|
1689
1754
|
end
|
1690
|
-
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1755
|
+
else
|
1756
|
+
if range.include?(kk=itv_minside(j)) && pcmp(j, kk) == 0
|
1757
|
+
k = kk
|
1758
|
+
elsif range.include?(kk=itv_parent_maxside(j)) && pcmp(j, kk) == 0
|
1759
|
+
k = kk
|
1694
1760
|
end
|
1695
|
-
|
1696
|
-
|
1761
|
+
end
|
1762
|
+
if !k
|
1763
|
+
nil
|
1764
|
+
elsif scmp(k, j) > 0
|
1765
|
+
k
|
1766
|
+
else
|
1767
|
+
nil
|
1768
|
+
end
|
1769
|
+
}
|
1770
|
+
end
|
1771
|
+
|
1772
|
+
def itv_downheap_sub(i, range)
|
1773
|
+
itv_travel(i, range, false) {|j|
|
1774
|
+
k1 = k2 = nil
|
1775
|
+
if itv_minside?(j)
|
1776
|
+
if range.include?(kk=itv_maxside(j)) && pcmp(j, kk) == 0
|
1777
|
+
k1 = kk
|
1697
1778
|
else
|
1698
|
-
|
1779
|
+
k1 = kk if range.include?(kk=itv_child1_minside(j)) && pcmp(j, kk) == 0
|
1780
|
+
k2 = kk if range.include?(kk=itv_child2_minside(j)) && pcmp(j, kk) == 0
|
1699
1781
|
end
|
1700
|
-
|
1701
|
-
|
1782
|
+
else
|
1783
|
+
if range.include?(kk=itv_child1_minside(j)) && pcmp(j, kk) == 0
|
1784
|
+
k1 = kk
|
1785
|
+
elsif range.include?(kk=itv_child1_maxside(j)) && pcmp(j, kk) == 0
|
1786
|
+
k1 = kk
|
1787
|
+
end
|
1788
|
+
if range.include?(kk=itv_child2_minside(j)) && pcmp(j, kk) == 0
|
1789
|
+
k2 = kk
|
1790
|
+
elsif range.include?(kk=itv_child2_maxside(j)) && pcmp(j, kk) == 0
|
1791
|
+
k2 = kk
|
1792
|
+
end
|
1793
|
+
end
|
1794
|
+
if k1 && k2
|
1795
|
+
k = scmp(k1, k2) > 0 ? k2 : k1
|
1796
|
+
else
|
1797
|
+
k = k1 || k2
|
1798
|
+
end
|
1799
|
+
if k && scmp(k, j) < 0
|
1800
|
+
k
|
1801
|
+
else
|
1802
|
+
nil
|
1803
|
+
end
|
1804
|
+
}
|
1805
|
+
end
|
1702
1806
|
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1807
|
+
def itv_adjust(i, range)
|
1808
|
+
if itv_minside?(i)
|
1809
|
+
j = itv_upheap_minside(i, range)
|
1810
|
+
if i == j
|
1811
|
+
i = itv_downheap_minside(i, range)
|
1812
|
+
if !range.include?(itv_child1_minside(i)) && range.include?(j=itv_maxside(i)) && pcmp(i, j) > 0
|
1813
|
+
swap(i, j)
|
1814
|
+
i = j
|
1815
|
+
end
|
1816
|
+
if itv_maxside?(i) || !range.include?(itv_maxside(i))
|
1817
|
+
i = itv_upheap_maxside(i, range)
|
1818
|
+
end
|
1819
|
+
end
|
1820
|
+
else
|
1821
|
+
j = itv_upheap_maxside(i, range)
|
1822
|
+
if i == j
|
1823
|
+
i = itv_downheap_maxside(i, range)
|
1824
|
+
if !range.include?(itv_child1_maxside(i))
|
1825
|
+
if range.include?(j=itv_child1_minside(i)) && pcmp(j, i) > 0
|
1826
|
+
swap(i, j)
|
1827
|
+
i = j
|
1828
|
+
elsif range.include?(j=itv_minside(i)) && pcmp(j, i) > 0
|
1829
|
+
swap(i, j)
|
1710
1830
|
i = j
|
1711
|
-
end
|
1712
|
-
if maxside?(i) || !range.include?(maxside(i))
|
1713
|
-
i = upheap_maxside(q, ary, i, range)
|
1714
1831
|
end
|
1715
1832
|
end
|
1716
|
-
|
1717
|
-
|
1718
|
-
if i == j
|
1719
|
-
i = downheap_maxside(q, ary, i, range)
|
1720
|
-
if !range.include?(child1_maxside(i))
|
1721
|
-
if range.include?(j=child1_minside(i)) && pcmp(q, ary, j, i) > 0
|
1722
|
-
swap(ary, i, j)
|
1723
|
-
i = j
|
1724
|
-
elsif range.include?(j=minside(i)) && pcmp(q, ary, j, i) > 0
|
1725
|
-
swap(ary, i, j)
|
1726
|
-
i = j
|
1727
|
-
end
|
1728
|
-
end
|
1729
|
-
if minside?(i)
|
1730
|
-
i = upheap_minside(q, ary, i, range)
|
1731
|
-
end
|
1833
|
+
if itv_minside?(i)
|
1834
|
+
i = itv_upheap_minside(i, range)
|
1732
1835
|
end
|
1733
1836
|
end
|
1734
|
-
i = upheap_sub(q, ary, i, range)
|
1735
|
-
downheap_sub(q, ary, i, range)
|
1736
1837
|
end
|
1838
|
+
i = itv_upheap_sub(i, range)
|
1839
|
+
itv_downheap_sub(i, range)
|
1840
|
+
end
|
1737
1841
|
|
1738
|
-
|
1739
|
-
|
1740
|
-
|
1741
|
-
|
1742
|
-
|
1743
|
-
|
1744
|
-
|
1745
|
-
end
|
1842
|
+
def itv_update_prio(loc, prio, subprio)
|
1843
|
+
i = loc.send(:index)
|
1844
|
+
ei, pi, si = get_entry(i)
|
1845
|
+
set_entry(i, ei, prio, subprio)
|
1846
|
+
range = 0...self.size
|
1847
|
+
itv_adjust(i, range)
|
1848
|
+
end
|
1746
1849
|
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1757
|
-
|
1758
|
-
end
|
1759
|
-
currentsize
|
1850
|
+
def itv_heapify(heapsize=0)
|
1851
|
+
currentsize = self.size
|
1852
|
+
h = Math.log(currentsize+1)/Math.log(2)
|
1853
|
+
if currentsize - 1 < (h - 1) * (currentsize - heapsize + 1)
|
1854
|
+
(currentsize-1).downto(0) {|i|
|
1855
|
+
itv_adjust(i, i...currentsize)
|
1856
|
+
}
|
1857
|
+
else
|
1858
|
+
heapsize.upto(currentsize-1) {|i|
|
1859
|
+
itv_adjust(i, 0...(i+1))
|
1860
|
+
}
|
1760
1861
|
end
|
1862
|
+
currentsize
|
1863
|
+
end
|
1761
1864
|
|
1762
|
-
|
1763
|
-
|
1764
|
-
|
1765
|
-
|
1766
|
-
|
1767
|
-
|
1865
|
+
def itv_find_minmax_loc
|
1866
|
+
case self.size
|
1867
|
+
when 0
|
1868
|
+
[nil, nil]
|
1869
|
+
when 1
|
1870
|
+
e0, p0, s0 = get_entry(0)
|
1871
|
+
[e0, e0]
|
1872
|
+
else
|
1873
|
+
if pcmp(0, 1) == 0
|
1874
|
+
e0, p0, s0 = get_entry(0)
|
1768
1875
|
[e0, e0]
|
1769
1876
|
else
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
else
|
1774
|
-
e0, p0, s0 = get_entry(ary, 0)
|
1775
|
-
e1, p1, s1 = get_entry(ary, 1)
|
1776
|
-
[e0, e1]
|
1777
|
-
end
|
1877
|
+
e0, p0, s0 = get_entry(0)
|
1878
|
+
e1, p1, s1 = get_entry(1)
|
1879
|
+
[e0, e1]
|
1778
1880
|
end
|
1779
1881
|
end
|
1882
|
+
end
|
1780
1883
|
|
1781
|
-
|
1782
|
-
|
1783
|
-
|
1884
|
+
def itv_find_min_loc
|
1885
|
+
itv_find_minmax_loc.first
|
1886
|
+
end
|
1784
1887
|
|
1785
|
-
|
1786
|
-
|
1787
|
-
|
1888
|
+
def itv_find_max_loc
|
1889
|
+
itv_find_minmax_loc.last
|
1890
|
+
end
|
1788
1891
|
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
|
1795
|
-
|
1796
|
-
|
1797
|
-
|
1798
|
-
|
1799
|
-
end
|
1800
|
-
size(ary)
|
1892
|
+
def itv_delete_loc(loc)
|
1893
|
+
i = loc.send(:index)
|
1894
|
+
_, priority, subpriority = get_entry(i)
|
1895
|
+
last = self.size - 1
|
1896
|
+
loc.send(:internal_deleted, priority, subpriority)
|
1897
|
+
el, pl, sl = delete_entry(last)
|
1898
|
+
if i != last
|
1899
|
+
set_entry(i, el, pl, sl)
|
1900
|
+
el.send(:index=, i)
|
1901
|
+
itv_adjust(i, 0...last)
|
1801
1902
|
end
|
1903
|
+
self.size
|
1802
1904
|
end
|
1803
1905
|
|
1906
|
+
IntervalMode = {
|
1907
|
+
:update_prio => :itv_update_prio,
|
1908
|
+
:heapify => :itv_heapify,
|
1909
|
+
:find_minmax_loc => :itv_find_minmax_loc,
|
1910
|
+
:find_min_loc => :itv_find_min_loc,
|
1911
|
+
:find_max_loc => :itv_find_max_loc,
|
1912
|
+
:delete_loc => :itv_delete_loc
|
1913
|
+
}
|
1914
|
+
|
1915
|
+
Mode = {
|
1916
|
+
:min => MinMode,
|
1917
|
+
:max => MaxMode,
|
1918
|
+
:interval => IntervalMode
|
1919
|
+
}
|
1920
|
+
|
1804
1921
|
# :startdoc:
|
1805
1922
|
end
|