depq 0.3 → 0.4
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.
- 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
|