PriorityQueue 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,10 @@
1
+ 0.1.1
2
+ * Removed debug cruft
3
+ * Added more documentation and examples
4
+ * Readme typo fixed
5
+ * I had the tests commented out
6
+ * Removed a bug when pushing twice onto the c priority queue (and added a test)
7
+
1
8
  0.1.0
2
9
  * API changes
3
10
  * Added lots of unit tests
@@ -0,0 +1,140 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = /usr/lib/ruby/1.8/i486-linux
8
+ hdrdir = $(topdir)
9
+ VPATH = $(srcdir):$(topdir):$(hdrdir)
10
+ prefix = $(DESTDIR)/usr
11
+ exec_prefix = $(prefix)
12
+ sitedir = $(DESTDIR)/usr/local/lib/site_ruby
13
+ rubylibdir = $(libdir)/ruby/$(ruby_version)
14
+ archdir = $(rubylibdir)/$(arch)
15
+ sbindir = $(exec_prefix)/sbin
16
+ datadir = $(prefix)/share
17
+ includedir = $(prefix)/include
18
+ infodir = $(prefix)/info
19
+ sysconfdir = $(DESTDIR)/etc
20
+ mandir = $(datadir)/man
21
+ libdir = $(exec_prefix)/lib
22
+ sharedstatedir = $(prefix)/com
23
+ oldincludedir = $(DESTDIR)/usr/include
24
+ sitearchdir = $(sitelibdir)/$(sitearch)
25
+ bindir = $(exec_prefix)/bin
26
+ localstatedir = $(DESTDIR)/var
27
+ sitelibdir = $(sitedir)/$(ruby_version)
28
+ libexecdir = $(exec_prefix)/libexec
29
+
30
+ CC = gcc
31
+ LIBRUBY = $(LIBRUBY_SO)
32
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
33
+ LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
34
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
35
+
36
+ CFLAGS = -fPIC -Wall -g -O2 -fPIC
37
+ CPPFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
38
+ CXXFLAGS = $(CFLAGS)
39
+ DLDFLAGS =
40
+ LDSHARED = $(CC) -shared
41
+ AR = ar
42
+ EXEEXT =
43
+
44
+ RUBY_INSTALL_NAME = ruby1.8
45
+ RUBY_SO_NAME = ruby1.8
46
+ arch = i486-linux
47
+ sitearch = i486-linux
48
+ ruby_version = 1.8
49
+ ruby = /usr/bin/ruby1.8
50
+ RUBY = $(ruby)
51
+ RM = rm -f
52
+ MAKEDIRS = mkdir -p
53
+ INSTALL = /usr/bin/install -c
54
+ INSTALL_PROG = $(INSTALL) -m 0755
55
+ INSTALL_DATA = $(INSTALL) -m 644
56
+ COPY = cp
57
+
58
+ #### End of system configuration section. ####
59
+
60
+ preload =
61
+
62
+ libpath = $(libdir)
63
+ LIBPATH = -L"$(libdir)"
64
+ DEFFILE =
65
+
66
+ CLEANFILES =
67
+ DISTCLEANFILES =
68
+
69
+ extout =
70
+ extout_prefix =
71
+ target_prefix =
72
+ LOCAL_LIBS =
73
+ LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl -lcrypt -lm -lc
74
+ SRCS = priority_queue.c
75
+ OBJS = priority_queue.o
76
+ TARGET = priority_queue
77
+ DLLIB = $(TARGET).so
78
+ STATIC_LIB =
79
+
80
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
81
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
82
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
83
+
84
+ TARGET_SO = $(DLLIB)
85
+ CLEANLIBS = $(TARGET).so $(TARGET).il? $(TARGET).tds $(TARGET).map
86
+ CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
87
+
88
+ all: $(DLLIB)
89
+ static: $(STATIC_LIB)
90
+
91
+ clean:
92
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
93
+
94
+ distclean: clean
95
+ @-$(RM) Makefile extconf.h conftest.* mkmf.log
96
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
97
+
98
+ realclean: distclean
99
+ install: install-so install-rb
100
+
101
+ install-so: $(RUBYARCHDIR)
102
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
103
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
104
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
105
+ install-rb: pre-install-rb install-rb-default
106
+ install-rb-default: pre-install-rb-default
107
+ pre-install-rb pre-install-rb-default: $(RUBYLIBDIR)
108
+ $(RUBYARCHDIR):
109
+ $(MAKEDIRS) $@
110
+ $(RUBYLIBDIR):
111
+ $(MAKEDIRS) $@
112
+
113
+ site-install: site-install-so site-install-rb
114
+ site-install-so: install-so
115
+ site-install-rb: install-rb
116
+
117
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
118
+
119
+ .cc.o:
120
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
121
+
122
+ .cxx.o:
123
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
124
+
125
+ .cpp.o:
126
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
127
+
128
+ .C.o:
129
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
130
+
131
+ .c.o:
132
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
133
+
134
+ $(DLLIB): $(OBJS)
135
+ @-$(RM) $@
136
+ $(LDSHARED) $(DLDFLAGS) $(LIBPATH) -o $@ $(OBJS) $(LOCAL_LIBS) $(LIBS)
137
+
138
+
139
+
140
+ $(OBJS): ruby.h defines.h
data/README CHANGED
@@ -1,7 +1,7 @@
1
1
  # Ruby extension implementing a priority queue
2
2
 
3
3
  ## Description
4
- This is a fibonacy heap priority queue implementation. That means
4
+ This is a fibonacci-heap priority-queue implementation. That means
5
5
 
6
6
  insert: O(1)
7
7
  decrease_priority: Amortized O(1)
@@ -0,0 +1,49 @@
1
+ c_file = File.read("ext/priority_queue/CPriorityQueue/priority_queue.c")
2
+ rb_file = File.read("lib/priority_queue/ruby_priority_queue.rb")
3
+
4
+ c_comments = Hash.new { "" }
5
+
6
+ c_file.scan(%r(/\*(.*?)\*/\s*static\s+\w+\s*pq_(\w+)\(.*?\))m).each do | match |
7
+ c_comments[match[1]] = match[0].gsub(%r(\n\s*\* {0,1})m, "\n").strip
8
+ end
9
+
10
+ rb_comments = Hash.new { "" }
11
+
12
+ rb_file.scan(%r(((?:\n\s*#[^\n]*)*)\s*def\s+(\w+))m).each do | match |
13
+ rb_comments[match[1]] = match[0].gsub(%r(\n\s*# {0,1})m, "\n").strip
14
+ end
15
+
16
+ add_comments = Hash.new
17
+
18
+ (rb_comments.keys + c_comments.keys).uniq.each do | key |
19
+ #next if rb_comments[key].gsub(/\s+/m, " ") == c_comments[key].gsub(/\s+/m, " ")
20
+ if c_comments[key].empty?
21
+ add_comments[key] = rb_comments[key]
22
+ elsif rb_comments[key].empty?
23
+ add_comments[key] = c_comments[key]
24
+ elsif rb_comments[key] != c_comments[key]
25
+
26
+ puts key
27
+ puts "Ruby"
28
+ puts rb_comments[key]
29
+ puts "C"
30
+ puts c_comments[key]
31
+ puts
32
+ puts "Choose [c,r]"
33
+ 1 until /^([cr])/ =~ gets
34
+ add_comments[key] = ($1 == "c" ? c_comments : rb_comments)[key]
35
+ puts "-" * 80
36
+ puts
37
+ else
38
+ add_comments[key] = rb_comments[key]
39
+ end
40
+
41
+ end
42
+
43
+ File.open("lib/priority_queue/ruby_priority_queue.new.rb", "wb") do | o |
44
+ o <<
45
+ rb_file.gsub(%r(((?:\n\s*#[^\n]*)*)(\s*def\s+(\w+)))m) do | match |
46
+ name, all = $3, $2
47
+ "\n" + (add_comments[name].gsub(/^/, "#")) + all
48
+ end
49
+ end
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Ruby extension implementing a priority queue
5
5
  *
6
- * This is a fibonacy heap priority queue implementation.
6
+ * This is a fibonacci heap priority queue implementation.
7
7
  *
8
8
  * (c) 2005 Brian Schr�der
9
9
  *
@@ -514,8 +514,20 @@ VALUE pq_push(VALUE self, VALUE object, VALUE priority) {
514
514
  return self;
515
515
  }
516
516
 
517
- /*
518
- * Return the pair [object, priority] with minimal priority
517
+ /* call-seq:
518
+ * min -> [object, priority]
519
+ *
520
+ * Return the pair [object, priority] with minimal priority or nil when the
521
+ * queue is empty.
522
+ *
523
+ * q = PriorityQueue.new
524
+ * q["a"] = 10
525
+ * q["b"] = 20
526
+ * q.min #=> ["a", 10]
527
+ * q.delete_min #=> ["a", 10]
528
+ * q.min #=> ["b", 20]
529
+ * q.delete_min #=> ["b", 20]
530
+ * q.min #=> nil
519
531
  */
520
532
  static
521
533
  VALUE pq_min(VALUE self) {
@@ -528,8 +540,19 @@ VALUE pq_min(VALUE self) {
528
540
  return Qnil;
529
541
  }
530
542
 
531
- /*
532
- * Return the key that has the minimal priority
543
+ /* call-seq:
544
+ * min_key -> object
545
+ *
546
+ * Return the key that has the minimal priority or nil when the queue is empty.
547
+ *
548
+ * q = PriorityQueue.new
549
+ * q["a"] = 10
550
+ * q["b"] = 20
551
+ * q.min_key #=> "a"
552
+ * q.delete_min #=> ["a", 10]
553
+ * q.min_key #=> "b"
554
+ * q.delete_min #=> ["b", 20]
555
+ * q.min_key #=> nil
533
556
  */
534
557
  static
535
558
  VALUE pq_min_key(VALUE self) {
@@ -542,8 +565,19 @@ VALUE pq_min_key(VALUE self) {
542
565
  return Qnil;
543
566
  }
544
567
 
545
- /*
546
- * Return the minimal priority
568
+ /* call-seq:
569
+ * min_priority -> priority
570
+ *
571
+ * Return the minimal priority or nil when the queue is empty.
572
+ *
573
+ * q = PriorityQueue.new
574
+ * q["a"] = 10
575
+ * q["b"] = 20
576
+ * q.min_priority #=> 10
577
+ * q.delete_min #=> ["a", 10]
578
+ * q.min_priority #=> 20
579
+ * q.delete_min #=> ["b", 20]
580
+ * q.min_priority #=> nil
547
581
  */
548
582
  static
549
583
  VALUE pq_min_priority(VALUE self) {
@@ -556,8 +590,17 @@ VALUE pq_min_priority(VALUE self) {
556
590
  return Qnil;
557
591
  }
558
592
 
559
- /*
593
+ /* call-seq:
594
+ * delete_min -> [key, priority]
595
+ *
560
596
  * Delete key with minimal priority and return [key, priority]
597
+ *
598
+ * q = PriorityQueue.new
599
+ * q["a"] = 1
600
+ * q["b"] = 0
601
+ * q.delete_min #=> ["b", 0]
602
+ * q.delete_min #=> ["a", 1]
603
+ * q.delete_min #=> nil
561
604
  */
562
605
  static
563
606
  VALUE pq_delete_min(VALUE self) {
@@ -574,8 +617,17 @@ VALUE pq_delete_min(VALUE self) {
574
617
  }
575
618
  }
576
619
 
577
- /*
620
+ /* call-seq:
621
+ * delete_min_return_key -> key
622
+ *
578
623
  * Delete key with minimal priority and return the key
624
+ *
625
+ * q = PriorityQueue.new
626
+ * q["a"] = 1
627
+ * q["b"] = 0
628
+ * q.delete_min_return_key #=> "b"
629
+ * q.delete_min_return_key #=> "a"
630
+ * q.delete_min_return_key #=> nil
579
631
  */
580
632
  static
581
633
  VALUE pq_delete_min_return_key(VALUE self) {
@@ -593,7 +645,17 @@ VALUE pq_delete_min_return_key(VALUE self) {
593
645
  }
594
646
 
595
647
  /*
648
+ * call-seq:
649
+ * delete_min_return_priority -> priority
650
+ *
596
651
  * Delete key with minimal priority and return the priority value
652
+ *
653
+ * q = PriorityQueue.new
654
+ * q["a"] = 1
655
+ * q["b"] = 0
656
+ * q.delete_min_return_priority #=> 0
657
+ * q.delete_min_return_priority #=> 1
658
+ * q.delete_min_return_priority #=> nil
597
659
  */
598
660
  static
599
661
  VALUE pq_delete_min_return_priority(VALUE self) {
@@ -612,7 +674,9 @@ VALUE pq_delete_min_return_priority(VALUE self) {
612
674
 
613
675
  /*
614
676
  * call-seq:
615
- * queue[key] = priority
677
+ * [key] = priority
678
+ * change_priority(key, priority)
679
+ * push(key, priority)
616
680
  *
617
681
  * Set the priority of a key.
618
682
  *
@@ -641,7 +705,7 @@ VALUE pq_change_priority(VALUE self, VALUE object, VALUE priority) {
641
705
 
642
706
  /*
643
707
  * call-seq:
644
- * queue[key] -> priority
708
+ * [key] -> priority
645
709
  *
646
710
  * Return the priority of a key or nil if the key is not in the queue.
647
711
  *
@@ -663,6 +727,9 @@ VALUE pq_get_priority(VALUE self, VALUE object) {
663
727
  }
664
728
 
665
729
  /*
730
+ * call-seq:
731
+ * has_key? key -> boolean
732
+ *
666
733
  * Return false if the key is not in the queue, true otherwise.
667
734
  *
668
735
  * q = PriorityQueue.new
@@ -678,7 +745,9 @@ VALUE pq_has_key(VALUE self, VALUE object) {
678
745
 
679
746
  return NIL_P(node_pointer) ? Qfalse : Qtrue;
680
747
  }
681
- /*
748
+ /* call-seq:
749
+ * length -> Fixnum
750
+ *
682
751
  * Returns the number of elements of the queue.
683
752
  *
684
753
  * q = PriorityQueue.new
@@ -694,13 +763,17 @@ VALUE pq_length(VALUE self) {
694
763
  }
695
764
 
696
765
  /*
766
+ /* call-seq:
767
+ * delete(key) -> [key, priority]
768
+ * delete(key) -> nil
769
+ *
697
770
  * Delete a key from the priority queue. Returns nil when the key was not in
698
771
  * the queue and [key, priority] otherwise.
699
772
  *
700
773
  * q = PriorityQueue.new
701
774
  * (0..10).each do | i | q[i.to_s] = i end
702
- * q.delete(5) #=> ["5", 5]
703
- * q.delete(5) #=> nil
775
+ * q.delete(5) #=> ["5", 5]
776
+ * q.delete(5) #=> nil
704
777
  */
705
778
  static
706
779
  VALUE pq_delete(VALUE self, VALUE object) {
@@ -762,7 +835,7 @@ static
762
835
  VALUE pq_to_dot(VALUE self) {
763
836
  priority_queue* q = get_pq_from_value(self);
764
837
 
765
- VALUE result_string = rb_str_new2("digraph fibonaccy_heap {\n");
838
+ VALUE result_string = rb_str_new2("digraph fibonacci_heap {\n");
766
839
  if (q->rootlist) {
767
840
  priority_node* n1 = q->rootlist;
768
841
  do {
@@ -789,9 +862,10 @@ void pq_each_helper(priority_queue *q, priority_node *n, void *args) {
789
862
  };
790
863
 
791
864
  /*
792
- * Call the given block with each key, priority pair in the queue
865
+ * Call the given block with each [key, priority] pair in the queue
793
866
  *
794
- * Beware: Changing the queue in the block may lead to unwanted behaviour and even infinite loops.
867
+ * Beware: Changing the queue in the block may lead to unwanted behaviour and
868
+ * even infinite loops.
795
869
  */
796
870
  static
797
871
  VALUE pq_each(VALUE self) {
@@ -806,7 +880,7 @@ VALUE pq_insert_node(VALUE node, VALUE queue) {
806
880
  }
807
881
 
808
882
  static
809
- VALUE pq_init_copy(VALUE copy, VALUE orig) {
883
+ VALUE pq_initialize_copy(VALUE copy, VALUE orig) {
810
884
  if (copy == orig)
811
885
  return copy;
812
886
 
@@ -851,14 +925,14 @@ void Init_CPriorityQueue() {
851
925
 
852
926
  rb_define_alloc_func(cPriorityQueue, pq_alloc);
853
927
  rb_define_method(cPriorityQueue, "initialize", pq_init, 0);
854
- rb_define_method(cPriorityQueue, "initialize_copy", pq_init_copy, 1);
855
- rb_define_method(cPriorityQueue, "push", pq_push, 2);
928
+ rb_define_method(cPriorityQueue, "initialize_copy", pq_initialize_copy, 1);
856
929
  rb_define_method(cPriorityQueue, "min", pq_min, 0);
857
930
  rb_define_method(cPriorityQueue, "min_key", pq_min_key, 0);
858
931
  rb_define_method(cPriorityQueue, "min_priority", pq_min_priority, 0);
859
932
  rb_define_method(cPriorityQueue, "delete_min", pq_delete_min, 0);
860
933
  rb_define_method(cPriorityQueue, "delete_min_return_key", pq_delete_min_return_key, 0);
861
934
  rb_define_method(cPriorityQueue, "delete_min_return_priority", pq_delete_min_return_priority, 0);
935
+ rb_define_method(cPriorityQueue, "push", pq_change_priority, 2);
862
936
  rb_define_method(cPriorityQueue, "change_priority", pq_change_priority, 2);
863
937
  rb_define_method(cPriorityQueue, "[]=", pq_change_priority, 2);
864
938
  rb_define_method(cPriorityQueue, "priority", pq_get_priority, 1);
@@ -1,11 +1,11 @@
1
1
  # Pure ruby Priority Queue
2
- $stdout.sync = true
3
- $stderr.sync = true
4
-
5
2
  class RubyPriorityQueue
6
3
 
4
+ include Enumerable
5
+
7
6
  private
8
7
 
8
+ #
9
9
  def link_nodes(b1, b2)
10
10
  return link_nodes(b2, b1) if b2.priority < b1.priority
11
11
 
@@ -66,8 +66,8 @@ class RubyPriorityQueue
66
66
 
67
67
  return self
68
68
  end
69
-
70
- # Does not change length priority
69
+
70
+ # Does not change length
71
71
  def insert_tree(tree)
72
72
  if @rootlist == nil
73
73
  @rootlist = @min = tree
@@ -113,7 +113,7 @@ class RubyPriorityQueue
113
113
  raise "Child is neighbour" if c == self.left
114
114
  @child = c
115
115
  end
116
-
116
+
117
117
  def to_dot(only_down = false, known_nodes = [])
118
118
  p known_nodes.map { | n | n.dot_id }
119
119
  p self.dot_id
@@ -151,15 +151,24 @@ class RubyPriorityQueue
151
151
 
152
152
  public
153
153
 
154
+ # Returns the number of elements of the queue.
155
+ #
156
+ # q = PriorityQueue.new
157
+ # q.length #=> 0
158
+ # q[0] = 1
159
+ # q.length #=> 1
154
160
  attr_reader :length
155
161
 
162
+ # Create a new, empty PriorityQueue
156
163
  def initialize
157
164
  @nodes = Hash.new
158
165
  @rootlist = nil
159
166
  @min = nil
160
167
  @length = 0
161
168
  end
162
-
169
+
170
+ # Print a priority queue as a dot-graph. The output can be fed to dot from the
171
+ # vizgraph suite to create a tree depicting the internal datastructure.
163
172
  def to_dot
164
173
  r = ["digraph fibheap {"]
165
174
  #r << @rootlist.to_dot.join("\n") if @rootlist
@@ -175,11 +184,26 @@ class RubyPriorityQueue
175
184
  r
176
185
  end
177
186
 
187
+ # Call dot and gv displaying the datstructure
178
188
  def display_dot
179
189
  puts to_dot
180
190
  system "echo '#{to_dot}' | twopi -Tps -Groot=ROOT -Goverlap=false> /tmp/dotfile.ps; gv /tmp/dotfile.ps"
181
191
  end
182
-
192
+
193
+ # call-seq:
194
+ # [key] = priority
195
+ # change_priority(key, priority)
196
+ # push(key, priority)
197
+ #
198
+ # Set the priority of a key.
199
+ #
200
+ # q = PriorityQueue.new
201
+ # q["car"] = 50
202
+ # q["train"] = 50
203
+ # q["bike"] = 10
204
+ # q.min #=> ["bike", 10]
205
+ # q["car"] = 0
206
+ # q.min #=> ["car", 0]
183
207
  def change_priority(key, priority)
184
208
  return push(key, priority) unless @nodes[key]
185
209
 
@@ -202,7 +226,8 @@ class RubyPriorityQueue
202
226
 
203
227
  self
204
228
  end
205
-
229
+
230
+ # Add an object to the queue.
206
231
  def push(key, priority)
207
232
  return change_priority(key, priority) if @nodes[key]
208
233
  @nodes[key] = node = Node.new(key, priority)
@@ -219,49 +244,113 @@ class RubyPriorityQueue
219
244
  @length += 1
220
245
  self
221
246
  end
222
-
247
+
248
+ # Returns true if the array is empty, false otherwise.
223
249
  def empty?
224
250
  @rootlist.nil?
225
251
  end
226
252
 
253
+ # call-seq:
254
+ # [key] -> priority
255
+ #
256
+ # Return the priority of a key or nil if the key is not in the queue.
257
+ #
258
+ # q = PriorityQueue.new
259
+ # (0..10).each do | i | q[i.to_s] = i end
260
+ # q["5"] #=> 5
261
+ # q[5] #=> nil
227
262
  def [](key)
228
263
  @nodes[key] and @nodes[key].priority
229
264
  end
230
265
 
266
+ # call-seq:
267
+ # has_key? key -> boolean
268
+ #
269
+ # Return false if the key is not in the queue, true otherwise.
270
+ #
271
+ # q = PriorityQueue.new
272
+ # (0..10).each do | i | q[i.to_s] = i end
273
+ # q.has_key("5") #=> true
274
+ # q.has_key(5) #=> false
231
275
  def has_key?(key)
232
276
  @nodes.has_key?(key)
233
277
  end
234
278
 
235
279
  alias :[]= :push
236
280
 
281
+ # Call the given block with each [key, priority] pair in the queue
282
+ #
283
+ # Beware: Changing the queue in the block may lead to unwanted behaviour and
284
+ # even infinite loops.
237
285
  def each
238
286
  @nodes.each do | key, node |
239
287
  yield(key, node.priority)
240
288
  end
241
289
  end
242
290
 
243
- include Enumerable
244
-
291
+ # call-seq:
292
+ # min -> [object, priority]
293
+ #
294
+ # Return the pair [object, priority] with minimal priority or nil when the
295
+ # queue is empty.
296
+ #
297
+ # q = PriorityQueue.new
298
+ # q["a"] = 10
299
+ # q["b"] = 20
300
+ # q.min #=> ["a", 10]
301
+ # q.delete_min #=> ["a", 10]
302
+ # q.min #=> ["b", 20]
303
+ # q.delete_min #=> ["b", 20]
304
+ # q.min #=> nil
245
305
  def min
246
306
  [@min.key, @min.priority] rescue nil
247
307
  end
248
-
308
+
309
+ # call-seq:
310
+ # min_key -> object
311
+ #
312
+ # Return the key that has the minimal priority or nil when the queue is empty.
313
+ #
314
+ # q = PriorityQueue.new
315
+ # q["a"] = 10
316
+ # q["b"] = 20
317
+ # q.min_key #=> "a"
318
+ # q.delete_min #=> ["a", 10]
319
+ # q.min_key #=> "b"
320
+ # q.delete_min #=> ["b", 20]
321
+ # q.min_key #=> nil
249
322
  def min_key
250
323
  @min.key rescue nil
251
324
  end
252
-
325
+
326
+ # call-seq:
327
+ # min_priority -> priority
328
+ #
329
+ # Return the minimal priority or nil when the queue is empty.
330
+ #
331
+ # q = PriorityQueue.new
332
+ # q["a"] = 10
333
+ # q["b"] = 20
334
+ # q.min_priority #=> 10
335
+ # q.delete_min #=> ["a", 10]
336
+ # q.min_priority #=> 20
337
+ # q.delete_min #=> ["b", 20]
338
+ # q.min_priority #=> nil
253
339
  def min_priority
254
340
  @min.priority rescue nil
255
341
  end
256
-
257
- def delete_min_return_key
258
- delete_min[0] rescue nil
259
- end
260
-
261
- def delete_min_return_priority
262
- delete_min[1] rescue nil
263
- end
264
-
342
+
343
+ # call-seq:
344
+ # delete(key) -> [key, priority]
345
+ # delete(key) -> nil
346
+ #
347
+ # Delete a key from the priority queue. Returns nil when the key was not in
348
+ # the queue and [key, priority] otherwise.
349
+ #
350
+ # q = PriorityQueue.new
351
+ # (0..10).each do | i | q[i.to_s] = i end
352
+ # q.delete(5) #=> ["5", 5]
353
+ # q.delete(5) #=> nil
265
354
  def delete(key)
266
355
  return nil unless n = @nodes.delete(key)
267
356
 
@@ -298,6 +387,47 @@ class RubyPriorityQueue
298
387
  return [n.key, n.priority]
299
388
  end
300
389
 
390
+ # call-seq:
391
+ # delete_min_return_key -> key
392
+ #
393
+ # Delete key with minimal priority and return the key
394
+ #
395
+ # q = PriorityQueue.new
396
+ # q["a"] = 1
397
+ # q["b"] = 0
398
+ # q.delete_min_return_key #=> "b"
399
+ # q.delete_min_return_key #=> "a"
400
+ # q.delete_min_return_key #=> nil
401
+ def delete_min_return_key
402
+ delete_min[0] rescue nil
403
+ end
404
+
405
+ # call-seq:
406
+ # delete_min_return_priority -> priority
407
+ #
408
+ # Delete key with minimal priority and return the priority value
409
+ #
410
+ # q = PriorityQueue.new
411
+ # q["a"] = 1
412
+ # q["b"] = 0
413
+ # q.delete_min_return_priority #=> 0
414
+ # q.delete_min_return_priority #=> 1
415
+ # q.delete_min_return_priority #=> nil
416
+ def delete_min_return_priority
417
+ delete_min[1] rescue nil
418
+ end
419
+
420
+ # call-seq:
421
+ # delete_min -> [key, priority]
422
+ #
423
+ # Delete key with minimal priority and return [key, priority]
424
+ #
425
+ # q = PriorityQueue.new
426
+ # q["a"] = 1
427
+ # q["b"] = 0
428
+ # q.delete_min #=> ["b", 0]
429
+ # q.delete_min #=> ["a", 1]
430
+ # q.delete_min #=> nil
301
431
  def delete_min
302
432
  return nil if self.empty?
303
433
  result = self.min
@@ -351,7 +481,8 @@ class RubyPriorityQueue
351
481
 
352
482
  result
353
483
  end
354
-
484
+
485
+ # Returns a string representation of the priority queue.
355
486
  def inspect
356
487
  "<PriorityQueue: #{@nodes.map{|(_, n)| [n.key, n.priority]}.sort_by{|(_,p)|p}.inspect}>"
357
488
  end
Binary file
Binary file
data/t.rb ADDED
@@ -0,0 +1,18 @@
1
+ class T
2
+ def initialize
3
+ begin
4
+ raise "T"
5
+ rescue => e
6
+ e1 = e
7
+ end
8
+ begin
9
+ raise "T"
10
+ rescue => e
11
+ e2 = e
12
+ end
13
+ r1 = 12 rescue Object => e
14
+ p [e1, e2, e, r1]
15
+ end
16
+ end
17
+
18
+ T.new
@@ -93,6 +93,22 @@ module PriorityQueueTest
93
93
  assert_equal(false, @q.empty?, "Filled queue should return false on empty?")
94
94
  end
95
95
 
96
+ def test_push
97
+ 20.times do | i |
98
+ @q.push i, i+10
99
+ end
100
+
101
+ 20.times do | i |
102
+ @q.push i, i
103
+ end
104
+
105
+ 20.times do | i |
106
+ assert_equal([i, i], @q.delete_min)
107
+ end
108
+
109
+ assert_equal(nil, @q.delete_min)
110
+ end
111
+
96
112
  def test_push_pop
97
113
  20.times do | i |
98
114
  @q.push i, i
@@ -233,9 +249,6 @@ module PriorityQueueTest
233
249
  end
234
250
  qq = @q.dup
235
251
  until @q.empty?
236
- puts "--"
237
- puts @q.inspect
238
- puts qq.inspect
239
252
  assert_equal(@q.delete_min, qq.delete_min)
240
253
  end
241
254
  end
@@ -251,7 +264,7 @@ module PriorityQueueTest
251
264
  extend self
252
265
  end
253
266
 
254
- class CPriorityQueueTest #< Test::Unit::TestCase
267
+ class CPriorityQueueTest < Test::Unit::TestCase
255
268
  include PriorityQueueTest
256
269
 
257
270
  def setup
@@ -264,7 +277,7 @@ class CPriorityQueueTest #< Test::Unit::TestCase
264
277
  end
265
278
  @q.delete_min
266
279
  assert_equal(
267
- ['digraph fibonaccy_heap {',
280
+ ['digraph fibonacci_heap {',
268
281
  ' NODE [label="N1 (1)",shape=box];',
269
282
  ' NODE [label="N3 (3)",shape=box];',
270
283
  ' NODE [label="N4 (4)",shape=box];',
@@ -277,7 +290,7 @@ class CPriorityQueueTest #< Test::Unit::TestCase
277
290
 
278
291
  end
279
292
 
280
- class PoorPriorityQueueTest #< Test::Unit::TestCase
293
+ class PoorPriorityQueueTest < Test::Unit::TestCase
281
294
  include PriorityQueueTest
282
295
 
283
296
  def setup
metadata CHANGED
@@ -1,78 +1,67 @@
1
- --- !ruby/object:Gem::Specification
1
+ !ruby/object:Gem::Specification
2
2
  rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: PriorityQueue
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.0
6
+ version: 0.1.1
7
7
  date: 2005-10-26 00:00:00 +02:00
8
- summary: This is a fibonacy heap priority queue implementation
8
+ summary: This is a fibonacci-heap priority-queue implementation
9
9
  require_paths:
10
- - lib
11
- - lib
12
- - ext
10
+ - lib
11
+ - lib
12
+ - ext
13
13
  email: priority_queue@brian-schroeder.de
14
14
  homepage: http://ruby.brian-schroeder.de/priority_queue
15
15
  rubyforge_project:
16
- description: "This is a fibonacy heap priority queue implementation. That means insert:
17
- O(1) decrease_priority: Amortized O(1) delete_min: Amortized O(log n)
18
- This project is different from K. Kodamas PQueue in that it allows a decrease
19
- key operation. That makes PriorityQueue usable for algorithms like dijkstras
20
- shortest path algorithm, while PQueue is more suitable for Heapsort and the
21
- like."
16
+ description: "This is a fibonacci-heap priority-queue implementation. That means insert: O(1) decrease_priority: Amortized O(1) delete_min: Amortized O(log n) This project is different from K. Kodamas PQueue in that it allows a decrease key operation. That makes PriorityQueue usable for algorithms like dijkstras shortest path algorithm, while PQueue is more suitable for Heapsort and the like."
22
17
  autorequire: priority_queue.rb
23
18
  default_executable:
24
19
  bindir: bin
25
20
  has_rdoc: true
26
21
  required_ruby_version: !ruby/object:Gem::Version::Requirement
27
22
  requirements:
28
- -
29
- - ">"
30
- - !ruby/object:Gem::Version
31
- version: 0.0.0
23
+ - - ">"
24
+ - !ruby/object:Gem::Version
25
+ version: 0.0.0
32
26
  version:
33
27
  platform: ruby
34
28
  signing_key:
35
29
  cert_chain:
36
30
  authors:
37
- - Brian Schroeder
31
+ - Brian Schroeder
38
32
  files:
39
- - README
40
- - test.rb
41
- - CHANGELOG
42
- - setup.rb
43
- - doc
44
- - ext
45
- - lib
46
- - test
47
- - benchmark
48
- - doc/result-PriorityQueue.png
49
- - doc/results.png
50
- - doc/result-PoorPriorityQueue.png
51
- - doc/result-RubyPriorityQueue.png
52
- - ext/priority_queue
53
- - ext/priority_queue/extconf.rb
54
- - ext/priority_queue/priority_queue.c
55
- - lib/priority_queue.rb
56
- - lib/priority_queue
57
- - lib/priority_queue/poor_priority_queue.rb
58
- - lib/priority_queue/ruby_priority_queue.rb
59
- - test/priority_queue_test.rb
60
- - benchmark/result-PriorityQueue.gp
61
- - benchmark/result-RubyPriorityQueue.gp
62
- - benchmark/dijkstra.rb
63
- - benchmark/result-PoorPriorityQueue.gp
64
- - benchmark/result-CPriorityQueue.png
65
- - benchmark/results.csv
66
- - benchmark/results.png
67
- - benchmark/result-PoorPriorityQueue.png
68
- - benchmark/result-RubyPriorityQueue.png
69
- - benchmark/results.gp
70
- - benchmark/result-CPriorityQueue.gp
33
+ - t.rb
34
+ - Makefile
35
+ - priority_queue.so
36
+ - README
37
+ - priority_queue.o
38
+ - compare_comments.rb
39
+ - CHANGELOG
40
+ - setup.rb
41
+ - ext
42
+ - lib
43
+ - test
44
+ - benchmark
45
+ - ext/priority_queue
46
+ - ext/priority_queue/extconf.rb
47
+ - ext/priority_queue/priority_queue.c
48
+ - lib/priority_queue.rb
49
+ - lib/priority_queue
50
+ - lib/priority_queue/poor_priority_queue.rb
51
+ - lib/priority_queue/ruby_priority_queue.rb
52
+ - test/priority_queue_test.rb
53
+ - benchmark/dijkstra.rb
71
54
  test_files: []
55
+
72
56
  rdoc_options: []
57
+
73
58
  extra_rdoc_files: []
59
+
74
60
  executables: []
61
+
75
62
  extensions:
76
- - ext/priority_queue/extconf.rb
63
+ - ext/priority_queue/extconf.rb
77
64
  requirements: []
78
- dependencies: []
65
+
66
+ dependencies: []
67
+
@@ -1,8 +0,0 @@
1
- set term png
2
- set out 'result-CPriorityQueue.png'
3
- set xlabel 'Number of nodes'
4
- set ylabel 'Time in seconds (real)'
5
- set logscale xy
6
- set title 'Dijkstras Shortest Path Algorithm on Networks of different degrees'
7
- plot \
8
- 'results.csv' using 1:2 with lines title "CPriorityQueue (Graph of Degree: 16)"
@@ -1,8 +0,0 @@
1
- set term png
2
- set out 'result-PoorPriorityQueue.png'
3
- set xlabel 'Number of nodes'
4
- set ylabel 'Time in seconds (real)'
5
- set logscale xy
6
- set title 'Dijkstras Shortest Path Algorithm on Networks of different degrees'
7
- plot \
8
- 'results.csv' using 1:3 with lines title "PoorPriorityQueue (Graph of Degree: 16)"
@@ -1,6 +0,0 @@
1
- set term png
2
- set out 'result-PriorityQueue.png'
3
- set xlabel 'Number of nodes'
4
- set ylabel 'Time in seconds (real)'
5
- plot \
6
- 'results.csv' using 1:2 with lines title "PriorityQueue (Graph of Degree: 16)"
@@ -1,8 +0,0 @@
1
- set term png
2
- set out 'result-RubyPriorityQueue.png'
3
- set xlabel 'Number of nodes'
4
- set ylabel 'Time in seconds (real)'
5
- set logscale xy
6
- set title 'Dijkstras Shortest Path Algorithm on Networks of different degrees'
7
- plot \
8
- 'results.csv' using 1:4 with lines title "RubyPriorityQueue (Graph of Degree: 16)"
@@ -1,37 +0,0 @@
1
- size "CPriorityQueue (Graph of Degree: 16)" "PoorPriorityQueue (Graph of Degree: 16)" "RubyPriorityQueue (Graph of Degree: 16)"
2
- 100 0.00583611594306098 0.0372195773654514 0.0697224669986301
3
- 200 0.0115931034088135 0.0454702642228868 0.545423454708523
4
- 300 0.0729258590274387 0.480532619688246 0.325443373786079
5
- 400 0.189983632829454 0.993642012278239 0.342083692550659
6
- 500 0.196244796117147 1.43146456612481 0.533440616395738
7
- 600 0.202457533942329 2.06269836425781 0.600252681308322
8
- 700 0.264183335834079 2.801170402103 0.72682441605462
9
- 800 0.270467466778225 3.94072720739577 0.799134042527941
10
- 900 0.443829695383708 4.89565277099609 0.985143608517117
11
- 1000 0.465132978227403 6.15393000178867 1.00162262386746
12
- 2000 0.740832858615451 27.4882550504473 2.40040622817145
13
- 3000 1.07575758298238 55.2952709992727 3.59957594341702
14
- 4000 1.47195853127374 '' 4.79923190010919
15
- 5000 1.86880042817858 '' 6.23916390207079
16
- 6000 2.40524856249491 '' 7.67889030774434
17
- 7000 2.80519718594021 '' 9.1503213511573
18
- 8000 3.32880263858371 '' 11.0491805076599
19
- 9000 3.58584565586514 '' 11.493485238817
20
- 10000 3.9917475912306 '' 13.0166101190779
21
- 20000 8.20343301031325 '' 26.9999283419715
22
- 30000 13.1478295061323 '' 43.9837118784587
23
- 40000 16.7911659081777 '' ''
24
- 50000 22.3882454766168 '' ''
25
- 60000 26.7571367687649 '' ''
26
- 70000 29.91215411822 '' ''
27
- 80000 37.1148204538557 '' ''
28
- 90000 '' '' ''
29
- 100000 '' '' ''
30
- 200000 '' '' ''
31
- 300000 '' '' ''
32
- 400000 '' '' ''
33
- 500000 '' '' ''
34
- 600000 '' '' ''
35
- 700000 '' '' ''
36
- 800000 '' '' ''
37
- 900000 '' '' ''
@@ -1,10 +0,0 @@
1
- set term png
2
- set out 'results.png'
3
- set xlabel 'Number of nodes'
4
- set ylabel 'Time in seconds (real)'
5
- set logscale xy
6
- set title 'Dijkstras Shortest Path Algorithm using different PQ Implementations'
7
- plot \
8
- 'results.csv' using 1:2 with lines title "CPriorityQueue (Graph of Degree: 16)",\
9
- 'results.csv' using 1:3 with lines title "PoorPriorityQueue (Graph of Degree: 16)",\
10
- 'results.csv' using 1:4 with lines title "RubyPriorityQueue (Graph of Degree: 16)"
Binary file
Binary file
Binary file
data/test.rb DELETED
@@ -1,11 +0,0 @@
1
- class A
2
- def initialize a
3
- @a = a
4
- end
5
-
6
- def other_a(a)
7
- a.instance_eval { @a }
8
- end
9
- end
10
-
11
- p A.new(2).other_a(A.new(1))