-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathBinaryHeap.cs
More file actions
94 lines (71 loc) · 2.5 KB
/
BinaryHeap.cs
File metadata and controls
94 lines (71 loc) · 2.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
using System;
using System.Linq;
namespace AlgorithmsAndDataStructures.DataStructures.BinaryHeaps;
public abstract class BinaryHeap<T> where T : IComparable<T>
{
#pragma warning disable CA1051 // Do not declare visible instance fields
protected T[] Heap;
#pragma warning restore CA1051 // Do not declare visible instance fields
private int nextElementPointer = 1;
protected BinaryHeap(int maxCapacity = 8)
{
Heap = new T[maxCapacity + 1];
}
public int Size => nextElementPointer - 1;
public T[] GetHeap()
{
return Heap.Skip(1).ToArray().Clone() as T[];
}
protected abstract bool ShouldSwap(int current, int target);
protected abstract bool ShouldNotSwap(int current, int target);
protected abstract int GetSwapChildIndex(int rightChildIndex, int leftChildIndex);
public void Insert(T value)
{
if (nextElementPointer == Heap.Length) throw new ArgumentException("Heap is full");
Heap[nextElementPointer] = value;
Swim(nextElementPointer);
nextElementPointer++;
}
private void Swim(int nextElementPointer)
{
var current = nextElementPointer;
while (current > 1)
{
var parentIndex = current / 2;
if (Heap[current].CompareTo(Heap[parentIndex]) == 0) break;
if (ShouldNotSwap(current, parentIndex)) break;
if (ShouldSwap(current, parentIndex))
{
var tmp = Heap[parentIndex];
Heap[parentIndex] = Heap[current];
Heap[current] = tmp;
current = parentIndex;
}
}
}
public T GetTop()
{
if (nextElementPointer - 1 == 0) throw new ArgumentException("Heap is empty");
var result = Heap[1];
Heap[1] = Heap[nextElementPointer - 1];
Heap[nextElementPointer - 1] = default;
nextElementPointer--;
Sink(1);
return result;
}
private void Sink(int index)
{
var rightChildIndex = index * 2 + 1;
var leftChildIndex = index * 2;
var swapChildIndex = leftChildIndex;
if (leftChildIndex >= nextElementPointer) return;
if (rightChildIndex < nextElementPointer) swapChildIndex = GetSwapChildIndex(rightChildIndex, leftChildIndex);
if (!ShouldSwap(index, swapChildIndex))
{
var tmp = Heap[index];
Heap[index] = Heap[swapChildIndex];
Heap[swapChildIndex] = tmp;
Sink(swapChildIndex);
}
}
}