lazy_priority_queue 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []