lazy_priority_queue 0.0.0

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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/lazy_priority_queue.rb +144 -0
  3. metadata +47 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0fd645a3f0b657b9d5f8d406e3d1c36e88d4e9f0
4
+ data.tar.gz: 805c1d6fdc15a7604b05457c896009e6e4af17de
5
+ SHA512:
6
+ metadata.gz: 34178a91738b2884553b73555f9e1a5daaa4a60deb6735ff26fad10704aaf417bc8f244384256dec41eae70ca6343aeac2833581f4e5c8aca89d88e1904132b6
7
+ data.tar.gz: c963785af0360405e04a0bf0b6b4ce3cfd23e70f8c59a7c7eb710bc5b2bd2ab40f000dc603ea39757c5e1d124ce13b2fcfb7e345d3bc756992ceaa2aabce84a0
@@ -0,0 +1,144 @@
1
+ class LazyPriorityQueue
2
+
3
+ Node = Struct.new :element,
4
+ :key,
5
+ :rank,
6
+ :parent,
7
+ :left_child,
8
+ :right_sibling
9
+
10
+ def initialize top_condition, &heap_property
11
+ @roots = []
12
+ @references = {}
13
+ @top_condition = top_condition
14
+ @heap_property = heap_property
15
+ end
16
+
17
+ def enqueue element, key
18
+ raise 'The provided element already is in the queue.' if @references[element]
19
+
20
+ node = Node.new element, key, 0
21
+
22
+ @top = @top ? select(@top, node) : node
23
+ @roots << node
24
+ @references[element] = node
25
+
26
+ element
27
+ end
28
+
29
+ def change_priority element, new_key
30
+ node = @references[element]
31
+
32
+ raise 'Element provided is not in the queue.' unless node
33
+
34
+ test_node = node.clone
35
+ test_node.key = new_key
36
+ raise 'Priority can only be changed to a more prioritary value.' unless @heap_property[test_node, node]
37
+
38
+ node.key = new_key
39
+ node = sift_up node
40
+ @top = select(@top, node) unless node.parent
41
+
42
+ element
43
+ end
44
+
45
+ def peek
46
+ @top and @top.element
47
+ end
48
+
49
+ def dequeue
50
+ return unless @top
51
+
52
+ element = @top.element
53
+ @references.delete element
54
+ @roots.delete @top
55
+
56
+ child = @top.left_child
57
+
58
+ while child
59
+ next_child = child.right_sibling
60
+ child.parent = nil
61
+ child.right_sibling = nil
62
+ @roots << child
63
+ child = next_child
64
+ end
65
+
66
+ @roots = coalesce @roots
67
+ @top = @roots.inject { |top, node| select top, node }
68
+
69
+ element
70
+ end
71
+
72
+ def delete element
73
+ change_priority element, @top_condition
74
+ dequeue
75
+ end
76
+
77
+ def empty?; @references.empty? end
78
+ def size; @references.size end
79
+
80
+ private
81
+
82
+ def sift_up node
83
+ return node unless node.parent and not @heap_property[node.parent, node]
84
+
85
+ node.parent.key, node.key = node.key, node.parent.key
86
+ node.parent.element, node.element = node.element, node.parent.element
87
+
88
+ @references[node.element] = node
89
+ @references[node.parent.element] = node.parent
90
+
91
+ sift_up node.parent
92
+ end
93
+
94
+ def select parent_node, child_node
95
+ @heap_property[parent_node, child_node] ? parent_node : child_node
96
+ end
97
+
98
+ def coalesce trees
99
+ coalesced_trees = []
100
+
101
+ while tree = trees.pop
102
+ if coalesced_tree = coalesced_trees[tree.rank]
103
+ # This line must go before than...
104
+ coalesced_trees[tree.rank] = nil
105
+ # ...this one.
106
+ trees << add(tree, coalesced_tree)
107
+ else
108
+ coalesced_trees[tree.rank] = tree
109
+ end
110
+ end
111
+
112
+ coalesced_trees.compact
113
+ end
114
+
115
+ def add node_one, node_two
116
+ raise 'Both nodes must hold the same rank.' if node_one.rank != node_two.rank
117
+ raise 'Both nodes must be roots (no parents).' if node_one.parent || node_two.parent
118
+
119
+ adder_node, addend_node = @heap_property[node_one, node_two] ? [node_one, node_two] : [node_two, node_one]
120
+
121
+ addend_node.parent = adder_node
122
+
123
+ # This line must go before than...
124
+ addend_node.right_sibling = adder_node.left_child
125
+ # ...this one.
126
+ adder_node.left_child = addend_node
127
+
128
+ adder_node.rank += 1
129
+
130
+ adder_node
131
+ end
132
+ end
133
+
134
+ class MinPriorityQueue < LazyPriorityQueue
135
+ def initialize
136
+ super(-Float::INFINITY) { |parent_node, child_node| parent_node.key <= child_node.key }
137
+ end
138
+ end
139
+
140
+ class MaxPriorityQueue < LazyPriorityQueue
141
+ def initialize
142
+ super( Float::INFINITY) { |parent_node, child_node| parent_node.key >= child_node.key }
143
+ end
144
+ end
metadata ADDED
@@ -0,0 +1,47 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lazy_priority_queue
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Matías Battocchia
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-11 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Lazy priority queue is a priority queue which implements a lazy binomial
14
+ heap. It supports the change priority operation, being suitable for algorithms like
15
+ Dijkstra's shortest path and Prim's minimum spanning tree. It can be instantiated
16
+ as a min-priority queue as well as a max-priority queue.
17
+ email: matias@riseup.net
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - lib/lazy_priority_queue.rb
23
+ homepage: https://github.com/matiasbattocchia/lazy_priority_queue
24
+ licenses:
25
+ - MIT
26
+ metadata: {}
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubyforge_project:
43
+ rubygems_version: 2.4.5.1
44
+ signing_key:
45
+ specification_version: 4
46
+ summary: A priority queue which implements a lazy binomial heap.
47
+ test_files: []