17

Are there any heap data structure implementations out there, fibonacci, binary, or binomial?

Reference: These are data structures used to implement priority queues, not the ones used to allocate dynamic memory. See http://en.wikipedia.org/wiki/Heap_(data_structure)

Thanks, Dave

Dave Moore
  • 4,148
  • 6
  • 23
  • 34
  • http://stackoverflow.com/a/13776636/67824 – Ohad Schneider Dec 08 '12 at 13:06
  • See also https://stackoverflow.com/questions/102398/priority-queue-in-net – Colonel Panic Nov 05 '15 at 16:52
  • You may be interested in [this NuGet package](https://github.com/madelson/MedallionUtilities/tree/master/MedallionPriorityQueue), which implements a priority queue based on a binary heap. – ChaseMedallion Jul 29 '16 at 11:25
  • [Off Topic](http://stackoverflow.com/help/on-topic): *Some questions are still off-topic, … 4. Questions asking us to recommend or find a book, tool, software library, tutorial or other off-site resource* - that reduces on-topic answers to `yes`. – greybeard May 05 '17 at 05:30

7 Answers7

8

Free C# implementation of heaps and many other data structures:

Mitch Wheat
  • 280,588
  • 41
  • 444
  • 526
5

Stand alone stress tested implementations are in Github under Advanced-Algorithms repository (I own it). DecrementKey operation performance is what makes later two significant.

  • Binary Min/Max Heap
  • Binomial Min/Max Heap
  • Fibonacci Min/Max Heap

The repository has two more heap implementations, D-Ary Heap & Pairing Heap.

rustyx
  • 62,971
  • 18
  • 151
  • 210
justcoding121
  • 1,916
  • 1
  • 26
  • 31
5

QuickGraph implements Fibonacci Heaps and Queues in C#, among a whole lot of other stuff. It is free and open-source.

Roman Starkov
  • 52,420
  • 33
  • 225
  • 300
  • Documentation for QuickGraph is difficult to parse if you're just looking for a fib heap. Source code also isn't very clear. :( – MushinNoShin May 21 '15 at 17:02
2

I don't know of any native framework implementation.

I found two implementations of binary heap (link 1, link 2) and one implementation of binomial heap in f# (link).

Jakub Šturc
  • 32,938
  • 24
  • 85
  • 107
1

I believe that a SortedSet<KeyValuePair<K,V>> with a custom Comparer will do the job.

The Comparer will look like the following:

class KeyValueComparer<K, V> : IComparer<KeyValuePair<K,V>> where K:IComparable where V:IComparable
{
    public int Compare(KeyValuePair<K, V> x, KeyValuePair<K, V> y)
    {
        var res = x.Key.CompareTo(y.Key);
        return res == 0 ? x.Value.CompareTo(y.Value) : res;
    }
}

With such Comparer, the SortedSet will be sorted by Key and it will allow duplicates of keys.

You can get the Min at constant time, RemoveMin at O(logn), Add an entry at O(logn) and Update a key at O(logn).

Here is a full (or almost) implementation:

public class Heap<K, V>
    where K : IComparable
    where V : IComparable
{
    private readonly SortedSet<KeyValuePair<K, V>> _sortedSet;

    // O(1)
    public KeyValuePair<K, V> Min
    {
        get { return _sortedSet.Min; }
    }

    public Heap()
    {
        _sortedSet = new SortedSet<KeyValuePair<K, V>>(new KeyValueComparer<K, V>());
    } 

    // O(logn)
    public void Add(K key, V value)
    {
        _sortedSet.Add(new KeyValuePair<K, V>(key, value));
    }

    // O(logn)
    public KeyValuePair<K, V> RemoveMin()
    {
        var min = Min;
        _sortedSet.Remove(min);
        return min;
    }

    // O(logn)
    public void Remove(K key, V value)
    {
        _sortedSet.Remove(new KeyValuePair<K, V>(key, value));
    }

    // O(logn)
    public void UpdateKey(K oldKey, V oldValue, K newKey)
    {
        Remove(oldKey, oldValue);
        Add(newKey, oldValue);
    }

    private class KeyValueComparer<K, V> : IComparer<KeyValuePair<K, V>>
        where K : IComparable
        where V : IComparable
    {
        public int Compare(KeyValuePair<K, V> x, KeyValuePair<K, V> y)
        {
            var res = x.Key.CompareTo(y.Key);
            return res == 0 ? x.Value.CompareTo(y.Value) : res;
        }
    }
}
nbilal
  • 939
  • 2
  • 7
  • 20
  • 2
    According to wikipedia, using Fibonacci or pairing heap you could get O(1) for insertion: https://en.wikipedia.org/wiki/Pairing_heap#Summary_of_running_times – greenoldman Dec 22 '18 at 11:16
0

A Simple Min Heap Implementation.

https://github.com/bharathkumarms/AlgorithmsMadeEasy/blob/master/AlgorithmsMadeEasy/MinHeap.cs

using System;
using System.Collections.Generic;
using System.Linq;

namespace AlgorithmsMadeEasy
{
    public class MinHeap
    {
        private static int capacity = 10;
        private int size = 0;

        int[] items = new int[capacity];

        private int getLeftChildIndex(int parentIndex) { return 2*parentIndex+1 ; }
        private int getRightChildIndex(int parentIndex) { return 2*parentIndex+2 ; }
        private int getParentIndex(int childIndex) { return (childIndex - 1) / 2; }

        private bool hasLeftChild(int index) { return getLeftChildIndex(index) < size; }
        private bool hasRightChild(int index) { return getRightChildIndex(index) < this.size; }
        private bool hasParent(int index) { return getParentIndex(index) >= 0; }

        private int leftChild(int index) { return this.items[getLeftChildIndex(index)]; }
        private int rightChild(int index) { return this.items[getRightChildIndex(index)]; }
        private int parent(int index) { return this.items[this.getParentIndex(index)]; }

        private void swap(int indexOne, int indexTwo)
        {
            int temp = this.items[indexOne];
            this.items[indexOne] = this.items[indexTwo];
            this.items[indexTwo] = temp;
        }

        private void ensureExtraCapacity()
        {
            if (this.size == capacity)
            {
                Array.Resize(ref this.items, capacity*2);
                capacity *= 2;
            }
        }

        public int peek()
        {
            if(this.size==0) throw new NotSupportedException();
            return this.items[0];
        }

        public int remove()
        {
            if(this.size==0) throw new NotSupportedException();
            int item = this.items[0];
            items[0] = items[this.size - 1];
            items[this.size - 1] = 0;
            this.size--;
            heapifyDown();
            return item;
        }

        public void Add(int item)
        {
            this.ensureExtraCapacity();
            this.items[size] = item;
            this.size++;
            heapifyUp();
        }

        private void heapifyUp()
        {
            int index = this.size - 1;
            while (hasParent(index) && parent(index) > this.items[index])
            {
                swap(index,getParentIndex(index));
                index = getParentIndex(index);
            }
        }

        private void heapifyDown()
        {
            int index = 0;
            while (hasLeftChild(index))
            {
                int smallerChildIndex = getLeftChildIndex(index);
                if (hasRightChild(index) && rightChild(index) < leftChild(index))
                {
                    smallerChildIndex = getRightChildIndex(index);
                }

                if (this.items[index] < this.items[smallerChildIndex])
                {
                    break;
                }
                else
                {
                    swap(index,smallerChildIndex);
                }
                index = smallerChildIndex;
            }
        }
    }
}

/*
Calling Code:
    MinHeap mh = new MinHeap();
    mh.Add(10);
    mh.Add(5);
    mh.Add(2);
    mh.Add(1);
    mh.Add(50);
    int peek = mh.peek();
    mh.remove();
    int newPeek = mh.peek();
*/
Bharathkumar V
  • 166
  • 3
  • 12
0

Implementation of MinHeap and MaxHeap:

public abstract class Heap<T>
{
    private List<T> m_Vector;

    private void Swap(int i, int j)
    {
        var tmp = m_Vector[i];
        m_Vector[i] = m_Vector[j];
        m_Vector[j] = tmp;
    }

    protected abstract int Compare(T a, T b);

    private void SiftUp(int i)
    {
        if (i == 0)
        {
            return;
        }

        int parent = (i - 1) / 2;

        if (Compare(m_Vector[i], m_Vector[parent]) >= 0)
        {
            return;
        }

        Swap(i, parent);
        SiftUp(parent);
    }

    private void SiftDown(int i)
    {
        int left = i * 2 + 1;

        if (left >= m_Vector.Count)
        {
            return;
        }

        var right = left + 1;

        var child = left;

        if (right < m_Vector.Count)
        {
            if (Compare(m_Vector[left], m_Vector[right]) > 0)
            {
                child = right;
            }
        }

        if (Compare(m_Vector[i], m_Vector[child]) <= 0)
        {
            return;
        }

        Swap(i, child);
        SiftDown(child);
    }

    public Heap()
    {
        m_Vector = new List<T>();
    }

    public Heap(IEnumerable<T> elements)
    {
        m_Vector = new List<T>(elements);

        if (m_Vector.Count < 2)
        {
            return;
        }

        //
        // From the last parent, upwards, sift down. Each sift is O<1>.
        //
        for (int i = (m_Vector.Count - 2) / 2; i >= 0; i--)
        {
            SiftDown(i);
        }
    }

    public int Count { get { return m_Vector.Count; } }

    public void Add(T element)
    {
        m_Vector.Add(element);
        SiftUp(m_Vector.Count - 1);
    }

    public T Top
    {
        get
        {
            if (m_Vector.Count == 0)
            {
                throw new InvalidOperationException();
            }
            return m_Vector[0];
        }
    }

    public T Fetch()
    {
        if (m_Vector.Count == 0)
        {
            throw new InvalidOperationException();
        }

        T result = m_Vector[0];
        m_Vector[0] = m_Vector[m_Vector.Count - 1];
        m_Vector.RemoveAt(m_Vector.Count - 1);

        SiftDown(0);

        return result;
    }
}

public class MinHeap<T> : Heap<T> where T: IComparable 
{
    protected override int Compare(T a, T b)
    {
        return a.CompareTo(b);
    }

    public MinHeap() : base()
    {
    }

    public MinHeap(IEnumerable<T> elements) : base(elements)
    {
    }
}

public class MaxHeap<T> : Heap<T> where T : IComparable
{
    protected override int Compare(T a, T b)
    {
        return b.CompareTo(a);
    }

    public MaxHeap() : base()
    {
    }

    public MaxHeap(IEnumerable<T> elements) : base(elements)
    {
    }
}