-
Notifications
You must be signed in to change notification settings - Fork 1
/
PriorityQueue.cs
146 lines (121 loc) · 3.5 KB
/
PriorityQueue.cs
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* Priority Queue Implementation by Robert Whitehead 2011
*
* Overview:
* This is an implementation of a standard MinHeap-based implementation of a priority queue. This gives:
* Log(N) insert cost
* Log(N) extract cost
* Log(N) decreaseKey cost
*
*/
using System.Collections;
using System.Collections.Generic;
public class PriorityQueue {
private List<PriorityElement> _list;
private int end;
public PriorityQueue() {
end = 1; //Ideosyncracy of heaps
//Create a new list to hold the elements.
_list = new List<PriorityElement>();
//Fill up the 0th element (a bit hacky, but makes the math later on easier)
_list.Insert(0, null);
}
public void Enqueue(PriorityElement p) {
//Insert into the list
_list.Insert(end, p);
//'Bubble' up to the correct position
BubbleUp(end);
//Increase element count
end++;
}
public PriorityElement Dequeue() {
if (IsEmpty()) {
return null;
}
else {
//Store the top element in a temporary location
PriorityElement result = _list[1];
//Swap the top and bottom elements of the list
Swap(end - 1, 1);
//Set the bottom element to null (which is now the top element)
//-This is fine as we have saved it in a temporary location
_list[end - 1] = null;
end--;
BubbleDown();
return result;
}
}
public bool IsEmpty() {
return (end == 1);
}
private void BubbleUp(int index) {
//Top level item can't be bubbled up
if(index == 1) return;
//Init
int currentIndex = index;
int parentIndex = Parent(index);
//Try and move the element as high as possible, until something above it has a higher priority than it
while(_list[currentIndex].Beats(_list[parentIndex])) {
Swap(currentIndex, parentIndex);
currentIndex = parentIndex;
if(currentIndex == 1) return;
parentIndex = Parent(currentIndex);
}
}
private void BubbleDown() {
//If empty or containing one element, no need to bubble!
if(end == 2 || end == 1) return;
int currentIndex = 1;
int leftIndex = Left(currentIndex);
int rightIndex = Right(currentIndex);
//Keep look to see if the left or right node is higher priority- if so, swap them and move progressively down
while(true) {
//If the node has bot ha right and left element, check them
if(leftIndex < end && rightIndex < end) {
if (_list[leftIndex].Beats(_list[currentIndex]) || _list[rightIndex].Beats(_list[currentIndex])) {
int replaceIndex = rightIndex;
if(_list[leftIndex].Beats(_list[rightIndex])) replaceIndex = leftIndex;
Swap(currentIndex, replaceIndex);
currentIndex = replaceIndex;
leftIndex = Left(currentIndex);
rightIndex = Right(currentIndex);
}
else {
return;
}
}
//If no right element exits, just need to check the left
else if(leftIndex < end) {
if (_list[leftIndex].Beats(_list[currentIndex])) {
Swap(leftIndex, currentIndex);
return;
}
else return;
}
else {
return;
}
}
}
//Used for testing purposes
private bool verifyHeap() {
if(end == 1 || end == 2) return true;
for(int x = (end - 1); x >= 2; x--) {
if(_list[x].Beats(_list[Parent(x)])) return false;
}
return true;
}
private int Parent(int index) {
return (index % 2 == 1) ? (index - 1) / 2 : index / 2;
}
private int Left(int index) {
return index * 2;
}
private int Right(int index) {
return (index * 2) + 1;
}
private void Swap(int index0, int index1) {
PriorityElement temp = _list[index1];
_list[index1] = _list[index0];
_list[index0] = temp;
}
}