Guest User

Untitled

a guest
Jul 11th, 2023
29
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.30 KB | None | 0 0
  1. using System;
  2. using Unity.Collections;
  3.  
  4. namespace Utility.Collections {
  5.     /// <summary>
  6.     /// A Priority Queue implemented as a Binary Heap. Enqueue and dequeue both have a complexity of O(log(n)).
  7.     ///
  8.     /// The code is intended to maximise performance. It intentionally does not include safety checks,
  9.     /// and only offers the minimal API required to use it as the basis for Dijkstra or A* implementations.
  10.     /// </summary>
  11.     /// <typeparam name="V">The value type.</typeparam>
  12.     public struct NativeBinaryHeap<V> : IDisposable {
  13.         private readonly struct Element {
  14.             public readonly int key;
  15.             public readonly V   value;
  16.  
  17.             public Element(int key, V value) {
  18.                 this.key   = key;
  19.                 this.value = value;
  20.             }
  21.         }
  22.  
  23.         private          NativeArray<Element> data;
  24.         private readonly int                  capacity;
  25.         private readonly IntOrder             order;
  26.  
  27.         private readonly struct IntOrder : IOrder<int> {
  28.             public int Compare(int lhs, int rhs) => lhs.CompareTo(rhs);
  29.  
  30.             public int Minimum => int.MinValue;
  31.             public int Maximum => int.MaxValue;
  32.         }
  33.  
  34.         /// <summary>
  35.         /// Create a new <c>BinaryHeap</c>.
  36.         /// </summary>
  37.         /// <param name="capacity">The maximum number of elements that can be inserted.</param>
  38.         /// <param name="allocator">allocator</param>
  39.         public NativeBinaryHeap(int capacity, Allocator allocator) {
  40.             order              = new IntOrder();
  41.             data               = new NativeArray<Element>(capacity + 2, allocator);
  42.             data[0]            = new Element(order.Minimum, default);
  43.             this.capacity      = capacity;
  44.             data[capacity + 1] = new Element(order.Maximum, default);
  45.             Count              = 0;
  46.             Clear();
  47.         }
  48.  
  49.         /// <summary>
  50.         /// Removes all keys and values from the <c>BinaryHeap</c>.
  51.         /// </summary>
  52.         public void Clear() {
  53.             Count = 0;
  54.             for (int i = 1; i <= capacity; ++i) {
  55.                 data[i] = new Element(order.Maximum, default);
  56.             }
  57.         }
  58.  
  59.         /// <summary>
  60.         /// Returns the number of elements contained in the <c>BinaryHeap</c>.
  61.         /// </summary>
  62.         public int Count { get; private set; }
  63.  
  64.         /// <summary>
  65.         /// Enqueues an element.
  66.         ///
  67.         /// Throws if the <c>BinaryHeap</c> is already full.
  68.         /// </summary>
  69.         /// <param name="value">The value to insert.</param>
  70.         /// <param name="key">The key (priority) to insert.</param>
  71.         public void Enqueue(V value, int key) {
  72.             ++Count;
  73.             int hole = Count;
  74.             int pred = hole >> 1;
  75.             while (order.Compare(data[pred].key, key) > 0) {
  76.                 data[hole] =   data[pred];
  77.                 hole       =   pred;
  78.                 pred       >>= 1;
  79.             }
  80.  
  81.             data[hole] = new Element(key, value);
  82.         }
  83.  
  84.         /// <summary>
  85.         /// Removes the element with the smallest key (priority), and returns its value.
  86.         ///
  87.         /// Use <c>Count()</c> to determine the current size of the queue. If the queue is empty this method will return a nonsensical value.
  88.         /// </summary>
  89.         /// <returns>The value that was dequeued.</returns>
  90.         public V Dequeue() {
  91.             V min = data[1].value;
  92.  
  93.             int hole = 1;
  94.             int succ = 2;
  95.             int sz   = Count;
  96.  
  97.             while (succ < sz) {
  98.                 if (order.Compare(data[succ].key, data[succ + 1].key) > 0)
  99.                     succ++;
  100.                 data[hole] =   data[succ];
  101.                 hole       =   succ;
  102.                 succ       <<= 1;
  103.             }
  104.  
  105.             int pred = hole >> 1;
  106.             while (order.Compare(data[pred].key, data[sz].key) > 0) {
  107.                 data[hole] =   data[pred];
  108.                 hole       =   pred;
  109.                 pred       >>= 1;
  110.             }
  111.  
  112.             data[hole] = data[sz];
  113.  
  114.             data[Count] = new Element(order.Maximum, default);
  115.             Count       = sz - 1;
  116.  
  117.             return min;
  118.         }
  119.  
  120.         public void Dispose() {
  121.             data.Dispose();
  122.         }
  123.     }
  124. }
Advertisement
Add Comment
Please, Sign In to add comment