话不多说,先上代码
#include <stdio.h>
#include <stdlib.h>
//定义一个堆得结构体,
struct MyHeap
{
int* pnData; //指向数据的指针
int nSize; //当前堆中的元素个数
};
//调整数据,维持堆得性质,这个和上次heapify的作用一样
//只是这个时从子道父节点这样的判断而已。
int IncreaseKey(MyHeap* pHeap, int nPos)
{
//循环和他父节点判断,只要 nPos > 1他就有父节点
while (nPos > 1)
{
int nMax = pHeap->pnData[nPos];
int nParent = nPos / 2;
//如果他比父节点大,交换数据,并使判断进入父节点
//(因为只有父节点可能会影响堆得性质。他的数据改变了。)
if (nMax > pHeap->pnData[nParent])
{
pHeap->pnData[nPos] = pHeap->pnData[nParent];
pHeap->pnData[nParent] = nMax;
nPos = nParent;
}
else //否则堆没有被破坏,退出循环
{
break;
}
}
return 1;
}
//插入数据,这里pnHeap为要插入的队,nLen为当前堆得大小。
//nData为要插入的数据,这里注意报保证堆得空间足够。
int Insert(MyHeap* pHeap, int nData)
{
++pHeap->nSize; //添加数据到末尾
pHeap->pnData[pHeap->nSize] = nData;
IncreaseKey(pHeap, pHeap->nSize);
return 1;
}
//弹出堆中对大元素,并使堆得个数减一
int PopMaxHeap(MyHeap* pHeap)
{
int nMax = pHeap->pnData[1]; //得到最大元素
//不要忘记维持堆得性质,因为最大元素已经弹出了,主要思路就是
//同他最大孩子填充这里。
int nPos = 1; //起始位1,因为他弹出,所以是这里开始破坏堆得性质的
int nChild = nPos * 2; //他的左孩子的位置,
//循环填充,用最大孩子填充父节点
while (nChild <= pHeap->nSize)
{
int nTemp = pHeap->pnData[nChild];
if (nChild + 1 <= pHeap->nSize &&
nTemp < pHeap->pnData[nChild + 1])
{
++nChild;
nTemp = pHeap->pnData[nChild];
}
pHeap->pnData[nPos] = nTemp;
nPos = nChild;
nChild *= 2;
}
//最好一个用最末尾的填充。
pHeap->pnData[nPos] = pHeap->pnData[pHeap->nSize];
--pHeap->nSize; //堆个数量减一
return nMax; //返回最大值。
}
//程序入口main
int main()
{
MyHeap myHeap; //定义一个堆
myHeap.pnData = (int*)::malloc(sizeof(int) * 11); //申请数据空间
myHeap.nSize = 0; //初始大小为0
for (int i = 1; i <= 10; ++i) //给优先队列堆里添加数据
{
Insert(&myHeap, i);
}
for (int i = 1; i <= 10; ++i) //测试优先队列是否建立成功
{
printf("%d ", myHeap.pnData[i]);
}
printf("
");
while (myHeap.nSize > 0) //逐一弹出队列的最大值。并验证
{
printf("%d ", PopMaxHeap(&myHeap));
}
printf("
");
::free(myHeap.pnData); //最后不要忘记释放申请的空间
system("pause");
return 0;
}
其实用堆实现队列就是用完全二叉树的应用过程,如果对完全二叉树以及堆排序有比较扎实的基础知识,再加上网上的查找的资料,实现优先队列还是不难的。