PriorityQueue 0.1.0 → 0.1.1

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/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))