Advertisement
patkovskyi

BinaryHeapWithUpdates

Jul 10th, 2013
192
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.14 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3.  
  4. namespace Algorithms.Lib
  5. {
  6.     /// <summary>
  7.     /// Doesn't support duplicate values!
  8.     /// Yes, this breaks Liskov's principle. Sorry, Barbara!
  9.     /// </summary>    
  10.     public class BinaryHeapWithUpdates<TKey, TValue> : BinaryHeap<TKey, TValue>
  11.     {
  12.         protected readonly Dictionary<TValue, int> HeapIndexes;
  13.  
  14.         public BinaryHeapWithUpdates(IComparer<TKey> comparer, IEqualityComparer<TValue> valueComparer) : base(comparer)
  15.         {
  16.             HeapIndexes = new Dictionary<TValue, int>(valueComparer);
  17.         }
  18.  
  19.         public void UpdateKey(TValue value, TKey newKey)
  20.         {
  21.             int index;
  22.             if (!HeapIndexes.TryGetValue(value, out index))
  23.             {
  24.                 throw new ArgumentException("Value was not found in the heap.");
  25.             }
  26.  
  27.             var oldKey = Keys[index];
  28.             int comp = Comparer.Compare(newKey, oldKey);
  29.             Keys[index] = newKey;
  30.             if (comp < 0)
  31.             {
  32.                 // decrease-key
  33.                 BubbleUp(index);
  34.             }
  35.             else if (comp > 0)
  36.             {
  37.                 // increase-key
  38.                 BubbleDown(index);
  39.             }
  40.         }
  41.  
  42.         public override void Insert(TKey key, TValue value)
  43.         {
  44.             HeapIndexes.Add(value, Keys.Count);
  45.             base.Insert(key, value);
  46.         }
  47.  
  48.         public override KeyValuePair<TKey, TValue> ExtractMin()
  49.         {
  50.             var min = base.ExtractMin();
  51.             HeapIndexes.Remove(min.Value);
  52.             return min;
  53.         }
  54.  
  55.         protected override void Swap(int i, int j)
  56.         {
  57.             HeapIndexes[Values[i]] = j;
  58.             HeapIndexes[Values[j]] = i;
  59.             base.Swap(i, j);            
  60.         }
  61.     }
  62.  
  63.     /// <summary>
  64.     /// Supports duplicate keys, but without stable ordering guarantee.
  65.     /// Stable ordering can be achieved by adding version counter to each node (as done in boost).
  66.     /// </summary>    
  67.     public class BinaryHeap<TKey, TValue>
  68.     {
  69.         protected readonly IComparer<TKey> Comparer;
  70.         protected readonly List<TKey> Keys;
  71.         protected readonly List<TValue> Values;
  72.  
  73.         public BinaryHeap(IComparer<TKey> comparer)
  74.         {
  75.             this.Comparer = comparer;
  76.             Keys = new List<TKey>();
  77.             Values = new List<TValue>();
  78.         }
  79.  
  80.         // O(N)
  81.         public static BinaryHeap<TKey, TValue> Build(IEnumerable<KeyValuePair<TKey, TValue>> elements, IComparer<TKey> comparer)
  82.         {
  83.             var heap = new BinaryHeap<TKey, TValue>(comparer);
  84.             foreach (var element in elements)
  85.             {
  86.                 heap.Keys.Add(element.Key);
  87.                 heap.Values.Add(element.Value);
  88.             }
  89.  
  90.             for (int i = (heap.Keys.Count - 2) >> 1; i >= 0; i--)
  91.             {
  92.                 heap.BubbleDown(i);
  93.             }
  94.  
  95.             return heap;
  96.         }
  97.  
  98.         // O(logN)
  99.         public virtual void Insert(TKey key, TValue value)
  100.         {
  101.             Keys.Add(key);
  102.             Values.Add(value);
  103.             BubbleUp(Keys.Count - 1);
  104.         }
  105.  
  106.         // O(logN)
  107.         public virtual KeyValuePair<TKey, TValue> ExtractMin()
  108.         {
  109.             if (Keys.Count == 0)
  110.             {
  111.                 throw new InvalidOperationException("Cannot extract minimum from empty heap.");
  112.             }
  113.  
  114.             var p = new KeyValuePair<TKey, TValue>(Keys[0], Values[0]);
  115.             Keys[0] = Keys[Keys.Count - 1];
  116.             Values[0] = Values[Values.Count - 1];
  117.             Keys.RemoveAt(Keys.Count - 1);
  118.             Values.RemoveAt(Values.Count - 1);
  119.             BubbleDown(0);
  120.             return p;
  121.         }
  122.  
  123.         protected virtual void Swap(int i, int j)
  124.         {
  125.             TKey tmpKey = Keys[i];
  126.             TValue tmpVal = Values[i];
  127.  
  128.             Keys[i] = Keys[j];
  129.             Values[i] = Values[j];
  130.  
  131.             Keys[j] = tmpKey;
  132.             Values[j] = tmpVal;
  133.         }
  134.  
  135.         protected void BubbleUp(int index)
  136.         {
  137.             while (index > 0)
  138.             {
  139.                 int parent = (index - 1) >> 1;
  140.  
  141.                 // stop condition: element is not less than it's parent
  142.                 if (Comparer.Compare(Keys[parent], Keys[index]) <= 0) return;
  143.                 Swap(index, parent);
  144.                 index = parent;
  145.             }
  146.         }
  147.  
  148.         // this is also called Heapify
  149.         protected void BubbleDown(int index)
  150.         {
  151.             int lastParent = (Keys.Count - 2) >> 1;
  152.             while (index <= lastParent)
  153.             {
  154.                 int left = (index << 1) + 1;
  155.                 int right = left + 1;
  156.                 int min = index;
  157.                 if (left < Keys.Count && Comparer.Compare(Keys[left], Keys[min]) <= 0) min = left;
  158.                 if (right < Keys.Count && Comparer.Compare(Keys[right], Keys[min]) <= 0) min = right;
  159.  
  160.                 // stop condition: index element is not less than both children
  161.                 if (min == index) return;
  162.                 Swap(index, min);
  163.                 index = min;
  164.             }
  165.         }
  166.     }
  167. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement