public static void Pop <K, V>(UnsafeHeapMax *heap, out K key, out V val) where K : unmanaged, IComparable <K> where V : unmanaged { if (heap->_count <= 1) { throw new InvalidOperationException(HEAP_EMPTY); } heap->_count = heap->_count - 1; GetKeyVal(heap, 1, out key, out val); //the last node will be placed on top and then swapped downwards as far as necessarry GetKeyVal(heap, heap->_count, out K evacuateKey, out V evacuateVal); SetKeyVal(heap, 1, evacuateKey, evacuateVal); var swapItem = 1; var parent = 1; do { parent = swapItem; if ((2 * parent + 1) <= heap->_count) { // both children exist if (Key <K>(heap, parent).CompareTo(Key <K>(heap, 2 * parent)) <= 0) { swapItem = 2 * parent; } if (Key <K>(heap, swapItem).CompareTo(Key <K>(heap, 2 * parent + 1)) <= 0) { swapItem = 2 * parent + 1; } } else if ((2 * parent) <= heap->_count) { // only one child exists if (Key <K>(heap, parent).CompareTo(Key <K>(heap, 2 * parent)) <= 0) { swapItem = 2 * parent; } } // one if the parent's children are smaller or equal, swap them if (parent != swapItem) { // pull parent/swapItem values GetKeyVal <K, V>(heap, parent, out K tmpParentKey, out V tmpParentVal); GetKeyVal <K, V>(heap, swapItem, out K tmpSwapItemKey, out V tmpSwapItemVal); // switch them SetKeyVal(heap, swapItem, tmpParentKey, tmpParentVal); SetKeyVal(heap, parent, tmpSwapItemKey, tmpSwapItemVal); } } while (parent != swapItem); }
static void SetKeyVal <K, V>(UnsafeHeapMax *heap, int index, K key, V val) where K : unmanaged where V : unmanaged { var ptr = UnsafeBuffer.Element(heap->_items.Ptr, index, heap->_items.Stride); // write key *(K *)(ptr) = key; // write val, offset by keyStride *(V *)((byte *)ptr + heap->_keyStride) = val; }
static void GetKeyVal <K, V>(UnsafeHeapMax *heap, int index, out K key, out V val) where K : unmanaged where V : unmanaged { var ptr = UnsafeBuffer.Element(heap->_items.Ptr, index, heap->_items.Stride); // read key key = *(K *)(ptr); // read val, offset by keyStride val = *(V *)((byte *)ptr + heap->_keyStride); }
public static void Free(UnsafeHeapMax *heap) { if (heap == null) { return; } // free dynamic items separately if (heap->_items.Dynamic == 1) { UnsafeBuffer.Free(&heap->_items); } // clear memory *heap = default; // free heap Native.Free(heap); }
static void ExpandHeap(UnsafeHeapMax *heap) { Assert.Check(heap->_items.Dynamic == 1); // new buffer for elements UnsafeBuffer newItems = default; // initialize to double size of existing one UnsafeBuffer.InitDynamic(&newItems, heap->_items.Length * 2, heap->_items.Stride); // copy memory over from previous items UnsafeBuffer.Copy(heap->_items, 0, newItems, 0, heap->_items.Length); // free old buffer UnsafeBuffer.Free(&heap->_items); // replace buffer with new heap->_items = newItems; }
public static void Push <K, V>(UnsafeHeapMax *heap, K key, V val) where K : unmanaged, IComparable <K> where V : unmanaged { if (heap->_count == heap->_items.Length) { if (heap->_items.Dynamic == 1) { ExpandHeap(heap); } else { throw new InvalidOperationException(HEAP_FULL); } } // index we're bubbling up from var bubbleIndex = heap->_count; // assign new key/val to it SetKeyVal(heap, bubbleIndex, key, val); while (bubbleIndex != 1) { var parentIndex = bubbleIndex / 2; var parentIndexKey = *(K *)UnsafeBuffer.Element(heap->_items.Ptr, parentIndex, heap->_items.Stride); if (parentIndexKey.CompareTo(key) < 0) { GetKeyVal(heap, parentIndex, out K parentKey, out V parentVal); SetKeyVal(heap, bubbleIndex, parentKey, parentVal); SetKeyVal(heap, parentIndex, key, val); bubbleIndex = parentIndex; } else { break; } } heap->_count = heap->_count + 1; }
public static UnsafeList.Iterator <T> GetIterator <T>(UnsafeHeapMax *heap) where T : unmanaged { return(new UnsafeList.Iterator <T>(heap->_items, 1, heap->_count - 1)); }
static K Key <K>(UnsafeHeapMax *heap, int index) where K : unmanaged { return(*(K *)UnsafeBuffer.Element(heap->_items.Ptr, index, heap->_items.Stride)); }
public static void Clear(UnsafeHeapMax *heap) { heap->_count = 1; }
public static int Count(UnsafeHeapMax *heap) { return(heap->_count - 1); }
public static int Capacity(UnsafeHeapMax *heap) { return(heap->_items.Length - 1); }