https://github.com/mudge/fibonacci_heap
A Ruby implementation of the Fibonacci heap data structure.
https://github.com/mudge/fibonacci_heap
Last synced: 4 months ago
JSON representation
A Ruby implementation of the Fibonacci heap data structure.
- Host: GitHub
- URL: https://github.com/mudge/fibonacci_heap
- Owner: mudge
- License: mit
- Created: 2018-06-26T20:39:29.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2018-07-15T16:09:18.000Z (almost 8 years ago)
- Last Synced: 2025-05-08T18:53:38.188Z (about 1 year ago)
- Language: Ruby
- Homepage: https://rubygems.org/gems/fibonacci_heap
- Size: 53.7 KB
- Stars: 6
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Fibonacci Heap [](https://travis-ci.org/mudge/fibonacci_heap)
A Ruby implementation of the [Fibonacci heap](https://en.wikipedia.org/wiki/Fibonacci_heap) data structure ideal for use as a priority queue with [Dijkstra's algorithm](https://en.wikipedia.org/wiki/Dijkstra's_algorithm#Using_a_priority_queue).
**Current version:** 0.2.0
**Supported Ruby versions:** 1.8.7, 1.9.2, 1.9.3, 2.0, 2.1, 2.2, 2.3
## Installation
```
gem install fibonacci_heap -v '~> 0.2'
```
Or, in your `Gemfile`:
```ruby
gem 'fibonacci_heap', '~> 0.2'
```
## Usage
```ruby
require 'fibonacci_heap'
heap = FibonacciHeap::Heap.new
foo = FibonacciHeap::Node.new(1, 'foo')
bar = FibonacciHeap::Node.new(0, 'bar')
baz = FibonacciHeap::Node.new(2, 'baz')
heap.insert(foo)
heap.insert(bar)
heap.insert(baz)
heap.pop
#=> #
heap.decrease_key(baz, 0)
heap.pop
#=> #
```
## API Documentation
* [`FibonacciHeap::Heap`](#fibonacciheapheap)
* [`.new`](#fibonacciheapheapnew)
* [`#n`](#fibonacciheapheapn)
* [`#size`](#fibonacciheapheapn)
* [`#length`](#fibonacciheapheapn)
* [`#empty?`](#fibonacciheapheapempty)
* [`#min`](#fibonacciheapheapmin)
* [`#insert(x[, k])`](#fibonacciheapheapinsertx-k)
* [`#concat(h2)`](#fibonacciheapheapconcath2)
* [`#pop`](#fibonacciheapheappop)
* [`#decrease_key(x, k)`](#fibonacciheapheapdecrease_keyx-k)
* [`#delete(x)`](#fibonacciheapheapdeletex)
* [`#clear`](#fibonacciheapheapclear)
* [`FibonacciHeap::Node`](#fibonacciheapnode)
* [`new(key[, value])`](#fibonacciheapnodenewkey-value)
* [`key`](#fibonacciheapnodekey)
* [`value`](#fibonacciheapnodevalue)
* [`FibonacciHeap::InvalidKeyError`](#fibonacciheapinvalidkeyerror)
### `FibonacciHeap::Heap`
A Fibonacci Heap data structure.
A "mergeable heap" that supports several operations that run in
constant amortized time. Structured as a collection of rooted trees
that are min-heap ordered.
#### `FibonacciHeap::Heap.new`
```ruby
heap = FibonacciHeap::Heap.new
#=> #
```
Return a new, empty [`FibonacciHeap::Heap`](#fibonacciheapheap) instance.
#### `FibonacciHeap::Heap#n`
```ruby
heap = FibonacciHeap::Heap.new
heap.insert(FibonacciHeap::Node.new('foo'))
heap.n
#=> 1
heap.size
#=> 1
heap.length
#=> 1
```
Return the current number of nodes in the heap.
Aliased to `size` and `length`.
#### `FibonacciHeap::Heap#empty?`
```ruby
heap = FibonacciHeap::Heap.new
heap.empty?
#=> true
```
Returns whether or not the heap is empty.
#### `FibonacciHeap::Heap#min`
```ruby
heap = FibonacciHeap::Heap.new
heap.insert(FibonacciHeap::Node.new(1))
heap.insert(FibonacciHeap::Node.new(2))
heap.min
#=> #
```
Return the smallest [`FibonacciHeap::Node`](#fibonacciheapnode) node in the heap as determined by the node's `key`.
Will return `nil` if the heap is empty.
#### `FibonacciHeap::Heap#insert(x[, k])`
```ruby
heap = FibonacciHeap::Heap.new
node = FibonacciHeap::Node.new(1, 'foo')
node2 = FibonacciHeap::Node.new(0, 'bar')
heap.insert(node)
#=> #
heap.insert(node2, 100)
#=> #
```
Insert the given [`FibonacciHeap::Node`](#fibonacciheapnode) `x` into the heap with an optional key `k`.
Defaults to using `x`'s existing `key` for `k`.
#### `FibonacciHeap::Heap#concat(h2)`
```ruby
heap = FibonacciHeap::Heap.new
heap.insert(FibonacciHeap::Node.new(1, 'foo'))
heap2 = FibonacciHeap::Heap.new
heap2.insert(FibonacciHeap::Node.new(2, 'bar'))
heap3 = heap.concat(heap2)
#=> #>
heap3.pop
#=> #
heap3.pop
#=> #
```
Unite the given [`FibonacciHeap::Heap`](#fibonacciheapheap) `h2` with this one in a new [`FibonacciHeap::Heap`](#fibonacciheapheap).
As this will mutate both collections of rooted trees, attempting to use either the original heap or `h2` after `concat` has undefined behaviour.
#### `FibonacciHeap::Heap#pop`
```ruby
heap = FibonacciHeap::Heap.new
heap.insert(FibonacciHeap::Node.new(1, 'foo'))
heap.pop
#=> #
```
Remove and return the smallest [`FibonacciHeap::Node`](#fibonacciheapnode) from the heap.
#### `FibonacciHeap::Heap#decrease_key(x, k)`
```ruby
heap = FibonacciHeap::Heap.new
node = FibonacciHeap::Node.new(1, 'foo')
heap.insert(node)
heap.decrease_key(node, 0)
#=> #
```
Decrease the key of the given [`FibonacciHeap::Node`](#fibonacciheapnode) `x` to the new given key `k`.
The node must already be inserted into the heap and the key must be comparable.
Raises a [`FibonacciHeap::InvalidKeyError`](#fibonacciheapinvalidkeyerror) if the new key is greater than the current key.
#### `FibonacciHeap::Heap#delete(x)`
```ruby
heap = FibonacciHeap::Heap.new
node = FibonacciHeap::Node.new(1, 'foo')
heap.insert(node)
heap.delete(node)
#=> #
```
Deletes the given [`FibonacciHeap::Node`](#fibonacciheapnode) `x` from the heap.
The node must already be inserted into the heap.
#### `FibonacciHeap::Heap#clear`
```ruby
heap = FibonacciHeap::Heap.new
heap.insert(FibonacciHeap::Node.new(1, 'foo'))
heap.clear
#=> #
```
Remove all nodes from the heap, emptying it.
### `FibonacciHeap::Node`
A single node in a [`FibonacciHeap::Heap`](#fibonacciheapheap).
Used internally to form both min-heap ordered trees and circular, doubly linked lists.
#### `FibonacciHeap::Node.new(key[, value])`
```ruby
node = FibonacciHeap::Node.new(1)
#=> #
node = FibonacciHeap::Node.new(1, 'foo')
#=> #
```
Return a new [`FibonacciHeap::Node`](#fibonacciheapnode) with the given key `key` and an optional value `value`.
Defaults to using the `key` as the value.
#### `FibonacciHeap::Node#key`
```ruby
node = FibonacciHeap::Node.new(1, 'foo')
node.key
#=> 1
```
Return the current key of the node.
#### `FibonacciHeap::Node#value`
```ruby
node = FibonacciHeap::Node.new(1, 'foo')
node.value
#=> "foo"
```
Return the current value of the node.
### `FibonacciHeap::InvalidKeyError`
Raised when attempting to decrease a key but the new key is greater than the current key.
## How is this different from [PQueue](https://github.com/rubyworks/pqueue) or [algorithms](https://github.com/kanwei/algorithms)' [`Containers::PriorityQueue`](http://kanwei.github.io/algorithms/classes/Containers/PriorityQueue.html)?
PQueue and `Containers::PriorityQueue` are also implementations of a Priority Queue but my specific use-case required the ability to alter the priority (really, the `key`) of arbitrary nodes _after_ insertion. PQueue allows you to customise the comparison of nodes but this is only done at insertion time. Similarly, `Containers::PriorityQueue` does not allow you to alter the priority of a specific node (you can delete a single node by its priority but any other node with the same priority might be deleted instead).
Furthermore, as the [reference text](#references) for my implementation often relies on the user having references to the nodes in the heap (e.g. for [`decrease_key`](#fibonacciheapheapdecrease_keyx-k) and [`delete`](#fibonacciheapheapdeletex)), I wanted to make the notion of the [`Node`](#fibonacciheapnode) explicit in the API. By having the user initialize [`Node`](#fibonacciheapnode)s themselves, it then makes the passing of [`Node`](#fibonacciheapnode)s to methods such as [`insert`](#fibonacciheapheapinsertx-k), [`delete`](#fibonacciheapheapdeletex) and [`decrease_key`](#fibonacciheapheapdecrease_keyx-k) more consistent.
## References
* Cormen, T. H., Leiserson, C. E., Rivest, R. L. & Stein, C., [Introduction to Algorithms, Third Edition](https://mitpress.mit.edu/books/introduction-algorithms-third-edition).
## License
Copyright © 2018 Paul Mucur
Distributed under the MIT License.