depq 0.3 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -1,19 +1,22 @@
1
- = Depq - Feature Rich Double-Ended Priority Queue.
1
+ = Depq - Double-Ended Priority Queue
2
2
 
3
- = Features
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 don't need to maintain timestamps yourself
9
- * update priority - usable for Dijkstra's shortest path algorithm and various graph algorithms
10
- * implicit binary heap - most operations are O(log n) at worst
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
- = Install
15
+ == Install
13
16
 
14
17
  gem install depq
15
18
 
16
- = Links
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
- = Introduction
27
+ == Introduction
25
28
 
26
- == Simple Insertion/Deletion
29
+ === Simple Insertion/Deletion
27
30
 
28
31
  You can insert values into a Depq object.
29
- You can deletes the values from the object from ascending/descending order.
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
- == The Order
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" with delete_min.
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
- Note that delete_max is also stable.
86
+ delete_max is also stable.
85
87
  This means delete_max deletes the element with maximum priority with "minimum" subpriority.
86
88
 
87
- == Update Element
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
- This is done using Depq::Locator object.
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 #=> #<Depq::Locator: "mangosteen":2>
98
- p m.value #=> "mangosteen"
99
- p m.priority #=> 2
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
- = Internal Heap Algorithm
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
- = Author
177
+ == Author
162
178
 
163
179
  Tanaka Akira <akr@fsij.org>
164
180
 
165
- = License
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:
@@ -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
- # = Features
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 don't need to maintain timestamps yourself
35
- # * update priority - usable for Dijkstra's shortest path algorithm and various graph algorithms
36
- # * implicit binary heap - most operations are O(log n) at worst
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
- # = Introduction
41
+ # == Introduction
39
42
  #
40
- # == Simple Insertion/Deletion
43
+ # === Simple Insertion/Deletion
41
44
  #
42
45
  # You can insert values into a Depq object.
43
- # You can deletes the values from the object from ascending/descending order.
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
- # == The Order
67
+ # === The Order
65
68
  #
66
- # The order is defined by the priorities corresnponds to the values and
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.inesrt 1, "Foo" # specify the priority for 1 as "Foo"
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" with delete_min.
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
- # == Update Element
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
- # This is done using Depq::Locator object.
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
- # = Internal Heap Algorithm
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 depq.
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 == MinHeap || @mode == IntervalHeap
482
+ if @mode == :min || @mode == :interval
447
483
  if @heapsize < self.size
448
- @heapsize = @mode.heapify(self, @ary, @heapsize)
484
+ @heapsize = mode_call(:heapify, @heapsize)
449
485
  end
450
486
  else
451
- @mode = MinHeap
452
- @heapsize = @mode.heapify(self, @ary)
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 == MaxHeap || @mode == IntervalHeap
494
+ if @mode == :max || @mode == :interval
459
495
  if @heapsize < self.size
460
- @heapsize = @mode.heapify(self, @ary, @heapsize)
496
+ @heapsize = mode_call(:heapify, @heapsize)
461
497
  end
462
498
  else
463
- @mode = MaxHeap
464
- @heapsize = @mode.heapify(self, @ary)
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 == IntervalHeap
506
+ if @mode == :interval
471
507
  if @heapsize < self.size
472
- @heapsize = @mode.heapify(self, @ary, @heapsize)
508
+ @heapsize = mode_call(:heapify, @heapsize)
473
509
  end
474
510
  else
475
- @mode = IntervalHeap
476
- @heapsize = @mode.heapify(self, @ary)
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 = @mode.heapify(self, @ary)
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
- @mode.update_prio(self, @ary, loc, priority, subpriority)
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
- @mode.find_min_loc(self, @ary)
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
- @mode.find_max_loc(self, @ary)
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 @mode.find_minmax_loc(self, @ary)
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 = @mode.delete_loc(self, @ary, loc)
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 = @mode.find_min_loc(self, @ary)
942
- @heapsize = @mode.delete_loc(self, @ary, loc)
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 = @mode.find_max_loc(self, @ary)
1007
- @heapsize = @mode.delete_loc(self, @ary, loc)
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
- module HeapArray
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
- def set_entry(ary, i, locator, priority, subpriority)
1320
- tmp = Array.new(ARY_SLICE_SIZE)
1321
- tmp[0] = locator
1322
- tmp[1] = priority
1323
- tmp[2] = subpriority
1324
- ary[i*ARY_SLICE_SIZE, ARY_SLICE_SIZE] = tmp
1325
- end
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
- def delete_entry(ary, i)
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
- def swap(ary, i, j)
1334
- ei, pi, si = get_entry(ary, i)
1335
- ej, pj, sj = get_entry(ary, j)
1336
- set_entry(ary, i, ej, pj, sj)
1337
- set_entry(ary, j, ei, pi, si)
1338
- ei.send(:index=, j)
1339
- ej.send(:index=, i)
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
- module SimpleHeap
1344
- include HeapArray
1345
-
1346
- def upheap(q, ary, j)
1347
- while true
1348
- return if j <= 0
1349
- i = (j-1) >> 1
1350
- return if upper?(q, ary, i, j)
1351
- swap(ary, j, i)
1352
- j = i
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
- def downheap(q, ary, i)
1357
- while true
1358
- j = i*2+1
1359
- k = i*2+2
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
- def find_top_loc(q, ary)
1375
- loc, _ = get_entry(ary, 0)
1376
- loc
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
- def delete_loc(q, ary, loc)
1380
- i = loc.send(:index)
1381
- _, priority, subpriority = get_entry(ary, i)
1382
- last = size(ary) - 1
1383
- loc.send(:internal_deleted, priority, subpriority)
1384
- el, pl, sl = delete_entry(ary, last)
1385
- if i != last
1386
- set_entry(ary, i, el, pl, sl)
1387
- el.send(:index=, i)
1388
- downheap(q, ary, i)
1389
- end
1390
- size(ary)
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
- def heapify(q, ary, heapsize=0)
1394
- # compare number of data movements in worst case.
1395
- # choose a way for less data movements.
1396
- #
1397
- # current size = ary.size / ARY_SLICE_SIZE = n
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
- module MinHeap
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
- def upper?(q, ary, i, j)
1446
- ei, pi, si = get_entry(ary, i)
1447
- ej, pj, sj = get_entry(ary, j)
1448
- q.send(:compare_for_min, pi, si, pj, sj) <= 0
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
- def update_prio(q, ary, loc, priority, subpriority)
1452
- i = loc.send(:index)
1453
- ei, pi, si = get_entry(ary, i)
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
- alias find_min_loc find_top_loc
1547
+ def min_heapify(heapsize=0)
1548
+ mm_heapify heapsize, method(:min_upper?)
1466
1549
  end
1467
1550
 
1468
- module MaxHeap
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
- def upper?(q, ary, i, j)
1474
- ei, pi, si = get_entry(ary, i)
1475
- ej, pj, sj = get_entry(ary, j)
1476
- q.send(:compare_for_max, pi, si, pj, sj) >= 0
1477
- end
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
- def update_prio(q, ary, loc, priority, subpriority)
1480
- i = loc.send(:index)
1481
- ei, pi, si = get_entry(ary, i)
1482
- subpriority ||= si
1483
- cmp = q.send(:compare_for_max, pi, si, priority, subpriority)
1484
- set_entry(ary, i, ei, priority, subpriority)
1485
- if cmp < 0
1486
- # loc.priority < priority
1487
- upheap(q, ary, i)
1488
- elsif cmp > 0
1489
- # loc.priority > priority
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
- module IntervalHeap
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
- def root?(i) i < 2 end
1503
- def minside?(i) i.even? end
1504
- def maxside?(i) i.odd? end
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
- def pcmp(q, ary, i, j)
1515
- ei, pi, si = get_entry(ary, i)
1516
- ej, pj, sj = get_entry(ary, j)
1517
- q.compare_priority(pi, pj)
1518
- end
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
- def scmp(q, ary, i, j)
1521
- ei, pi, si = get_entry(ary, i)
1522
- ej, pj, sj = get_entry(ary, j)
1523
- si <=> sj
1524
- end
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
- def psame(q, ary, i)
1527
- pcmp(q, ary, minside(i), maxside(i)) == 0
1528
- end
1630
+ def itv_psame(i)
1631
+ pcmp(itv_minside(i), itv_maxside(i)) == 0
1632
+ end
1529
1633
 
1530
- def travel(q, ary, i, range, fix_subpriority)
1531
- while true
1532
- j = yield i
1533
- return i if !j
1534
- swap ary, i, j
1535
- if fix_subpriority
1536
- imin = minside(i)
1537
- imax = maxside(i)
1538
- if range.include?(imin) && range.include?(imax)
1539
- if pcmp(q, ary, imin, imax) == 0 && scmp(q, ary, imin, imax) > 0
1540
- swap ary, imin, imax
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
- def upheap_minside(q, ary, i, range)
1549
- travel(q, ary, i, range, true) {|j|
1550
- if root?(j)
1551
- nil
1552
- elsif !range.include?(k = parent_minside(j))
1553
- nil
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
- if pcmp(q, ary, k, j) > 0
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
- end
1665
+ end
1666
+ }
1667
+ end
1564
1668
 
1565
- def upheap_maxside(q, ary, i, range)
1566
- travel(q, ary, i, range, true) {|j|
1567
- if root?(j)
1568
- nil
1569
- elsif !range.include?(k = parent_maxside(j))
1570
- nil
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
- if pcmp(q, ary, k, j) < 0
1573
- k
1574
- else
1575
- nil
1576
- end
1679
+ nil
1577
1680
  end
1578
- }
1579
- end
1681
+ end
1682
+ }
1683
+ end
1580
1684
 
1581
- def downheap_minside(q, ary, i, range)
1582
- travel(q, ary, i, range, true) {|j|
1583
- k1 = child1_minside(j)
1584
- k2 = child2_minside(j)
1585
- if !range.include?(k1)
1586
- nil
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 !range.include?(k2)
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
- if (pc = pcmp(q, ary, k1, k2)) < 0
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
- end
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
- if !range.include?(k2)
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
- end
1710
+ end
1711
+ }
1712
+ end
1641
1713
 
1642
- def upheap_sub(q, ary, i, range)
1643
- travel(q, ary, i, range, false) {|j|
1644
- k = nil
1645
- if minside?(j)
1646
- if range.include?(kk=parent_maxside(j)) && pcmp(q, ary, j, kk) == 0
1647
- k = kk
1648
- elsif range.include?(kk=parent_minside(j)) && pcmp(q, ary, j, kk) == 0
1649
- k = kk
1650
- end
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 range.include?(kk=minside(j)) && pcmp(q, ary, j, kk) == 0
1653
- k = kk
1654
- elsif range.include?(kk=parent_maxside(j)) && pcmp(q, ary, j, kk) == 0
1655
- k = kk
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 !k
1659
- nil
1660
- elsif scmp(q, ary, k, j) > 0
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
- end
1742
+ end
1743
+ }
1744
+ end
1667
1745
 
1668
- def downheap_sub(q, ary, i, range)
1669
- travel(q, ary, i, range, false) {|j|
1670
- k1 = k2 = nil
1671
- if minside?(j)
1672
- if range.include?(kk=maxside(j)) && pcmp(q, ary, j, kk) == 0
1673
- k1 = kk
1674
- else
1675
- k1 = kk if range.include?(kk=child1_minside(j)) && pcmp(q, ary, j, kk) == 0
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
- if k1 && k2
1691
- k = scmp(q, ary, k1, k2) > 0 ? k2 : k1
1692
- else
1693
- k = k1 || k2
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
- if k && scmp(q, ary, k, j) < 0
1696
- k
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
- nil
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
- end
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
- def adjust(q, ary, i, range)
1704
- if minside?(i)
1705
- j = upheap_minside(q, ary, i, range)
1706
- if i == j
1707
- i = downheap_minside(q, ary, i, range)
1708
- if !range.include?(child1_minside(i)) && range.include?(j=maxside(i)) && pcmp(q, ary, i, j) > 0
1709
- swap(ary, i, j)
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
- else
1717
- j = upheap_maxside(q, ary, i, range)
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
- def update_prio(q, ary, loc, prio, subprio)
1739
- i = loc.send(:index)
1740
- ei, pi, si = get_entry(ary, i)
1741
- subpriority ||= si
1742
- set_entry(ary, i, ei, prio, subprio)
1743
- range = 0...size(ary)
1744
- adjust(q, ary, i, range)
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
- def heapify(q, ary, heapsize=0)
1748
- currentsize = size(ary)
1749
- h = Math.log(currentsize+1)/Math.log(2)
1750
- if currentsize - 1 < (h - 1) * (currentsize - heapsize + 1)
1751
- (currentsize-1).downto(0) {|i|
1752
- adjust(q, ary, i, i...currentsize)
1753
- }
1754
- else
1755
- heapsize.upto(currentsize-1) {|i|
1756
- adjust(q, ary, i, 0...(i+1))
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
- def find_minmax_loc(q, ary)
1763
- case size(ary)
1764
- when 0
1765
- [nil, nil]
1766
- when 1
1767
- e0, p0, s0 = get_entry(ary, 0)
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
- if pcmp(q, ary, 0, 1) == 0
1771
- e0, p0, s0 = get_entry(ary, 0)
1772
- [e0, e0]
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
- def find_min_loc(q, ary)
1782
- find_minmax_loc(q, ary).first
1783
- end
1884
+ def itv_find_min_loc
1885
+ itv_find_minmax_loc.first
1886
+ end
1784
1887
 
1785
- def find_max_loc(q, ary)
1786
- find_minmax_loc(q, ary).last
1787
- end
1888
+ def itv_find_max_loc
1889
+ itv_find_minmax_loc.last
1890
+ end
1788
1891
 
1789
- def delete_loc(q, ary, loc)
1790
- i = loc.send(:index)
1791
- _, priority, subpriority = get_entry(ary, i)
1792
- last = size(ary) - 1
1793
- loc.send(:internal_deleted, priority, subpriority)
1794
- el, pl, sl = delete_entry(ary, last)
1795
- if i != last
1796
- set_entry(ary, i, el, pl, sl)
1797
- el.send(:index=, i)
1798
- adjust(q, ary, i, 0...last)
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