class PriorityQueue
{
private int[] Heap = new int[20];
private int count;
public void push(int num)
{
if (count > 19)
{
Console.WriteLine("堆满");
return;
}
Heap[count] = num;
shiftUp(count);
count++;
}
private void shiftUp(int count)
{
//Console.WriteLine("count:"+count);
while ((count+1)/2>0)
{
if (Heap[count] > Heap[count / 2])
{
//Console.WriteLine("Changed");
int temp = Heap[count];
Heap[count] = Heap[count / 2];
Heap[count / 2] = temp;
}
count /= 2;
}
/*foreach (int it in Heap)
{
if(it!=0)
Console.WriteLine(it);
}*/
}
public int top()
{
if (count == 0)
{
Console.WriteLine("堆空");
}
return Heap[0];
}
public int pop()
{
int top = Heap[0];
Heap[0] = Heap[count];
shiftDown();
count--;
return top;
}
private void shiftDown()
{
int curC = 0;
while (curC < count)
{
//右孩子大于左孩子
if (Heap[(curC + 1) * 2] > Heap[(curC + 1) * 2 - 1])
{
int temp = Heap[curC];
Heap[curC] = Heap[(curC + 1) * 2];
Heap[(curC + 1) * 2] = temp;
curC = (curC + 1) * 2;
}
else
{
int temp = Heap[curC];
Heap[curC] = Heap[(curC + 1) * 2-1];
Heap[(curC + 1) * 2-1] = temp;
curC = (curC + 1) * 2-1;
}
}
foreach (int it in Heap)
{
if(it!=0)
Console.WriteLine(it);
}
}
}
internal class Program
{
public static void Main(string[] args)
{
PriorityQueue que = new PriorityQueue();
que.push(1);
que.push(2);
que.push(4);
que.push(5);
que.push(7);
Console.WriteLine(que.top());
Console.WriteLine(que.pop());
Console.WriteLine(que.pop());
}
}
主要思想是堆排序里面的维护大/小堆。
Top一直指向堆顶,而push/pop要维护堆,pop出的值是Top。(注意:大根堆和小根堆只需要堆顶最大/小就行!)
伪代码方法:
push(参数)
{1.加入队尾
2.维护大/小根堆}
pop()
{1.返回堆顶
2.维护大/小根堆}
下面引用自:24只羊
堆和优先队列
2.1 堆中添加元素和Shift Up
现在我们要添加元素52,先添加到索引为10的位置,然而现在不满足二叉堆的性质,所以要调整52的位置,所以让52和自己的父亲节点依次与父亲节点相比较,如52大于父亲节点,就交换52与父亲节点的位置-------Shift
up2.2 堆中取出元素(最大值)和Shift Down
我们先取出最大值62,因为将两颗子树融合成一棵树比较复杂,所以我们可以把最小值16换到根节点,然后在采用shift-down操作,
shift-down:把16与左右两个孩子节点相比较,选择两个孩子中最大的那个元素,如果最大的那个元素比16大,则将16与它交换,很显然52与16做交换
探后继续与41做交换
因为16比15大,所以就完成啦