2009-01-09 10 views
14

¿Hay implementaciones de estructura de datos de montón por ahí, fibonacci, binario o binomial?¿Fibonacci, binario o montón binomial en C#?

Referencia: Estas son estructuras de datos utilizadas para implementar colas de prioridad, no los que se utilizan para asignar memoria dinámica. Ver http://en.wikipedia.org/wiki/Heap_(data_structure)

Gracias, de Dave

+0

Sólo por curiosidad, ¿qué estás escribiendo un montón de? – core

+0

http://stackoverflow.com/a/13776636/67824 –

+0

Ver también https://stackoverflow.com/questions/102398/priority-queue-in-net –

Respuesta

2

no sé de cualquier marco de implementación nativa.

encontré dos implementaciones de pila binaria (link 1, link 2) y una implementación de montón binomial en f # (link).

5

QuickGraph implementa Fibonacci Montones y colas en C#, entre en su conjunto muchas otras cosas Es gratis y de código abierto.

+0

Documentación para QuickGraph es difícil de analizar si sólo está buscando un montón fib. El código fuente tampoco es muy claro. :( – MushinNoShin

2

Creo que un SortedSet<KeyValuePair<K,V>> con una costumbre Comparer hará el trabajo.

El Comparer se verá como la siguiente:

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; 
    } 
} 

Con tales Comparer, la SortedSet estarán clasificados por la Llave y permitirá duplicados de llaves.

Puede obtener el Min en tiempo constante, RemoveMin en O(logn), Add una entrada en O(logn) y Update una llave en O(logn).

Aquí es una implementación completa (o casi):

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; 
     } 
    } 
} 
0

Un simple Min Montón de implementación.

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(); 
*/ 
3

de stands implementaciones probados solos estrés son en Github bajo Advanced-Algorithms repositorio. El rendimiento de la operación DecrementKey es lo que hace que los dos últimos sean significativos.

El repositorio tiene dos más implementaciones de almacenamiento dinámico, D-Ary Heap & Sincronización del montón.

0

Implementación de MinHeap y 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) 
    { 
    } 
} 
Cuestiones relacionadas