数据结构--优先列队(堆)的实现与相关操作
实现优先列队的最普遍的工具是二叉堆,有时也只叫做堆。
二叉堆有两个性质:结构性和堆序性。
结构性:堆是一颗被完全填满的二叉树,底层除外,底层元素从左到右依次填入,对于一个完全二叉树,用一个数组来表示一棵树,发现对于数组的任意位置i的元素,他的左儿子在2i处,右儿子在2i+1出,父亲在i/2向下取整处。
堆序性:如果想要快速找出最小元素,那么任意节点就应该小于它所有的后裔,如果想要快速找到最大的元素,则相反。
二叉堆在概念上抽象为一颗二叉树,满足上面的两个性质,在程序中则实际上为一个数组,同样满足上面的两个性质。
下面给出最小堆(即可以以常数时间找出最小元素)的一个代码实现:
#include<iostream>
using namespace std;
#define MinPQSize 10
#define MinData -1
struct Heapstruct;
typedef struct Heapstruct* PriorityQueue;
struct Heapstruct
{
int Capacity;
int Size;
int *Elements;
};
PriorityQueue Init_priorityqueue(int MaxElements) //创建并初始化一个优先列队
{
PriorityQueue H;
if(MaxElements < MinPQSize) cout << "Priority queue size is too small" << endl;
H = (PriorityQueue)malloc(sizeof(Heapstruct));
if(H == NULL) cout << "out of space" << endl;
H->Elements = (int*)malloc(sizeof(int) * MaxElements + 1);
if(H->Elements == NULL) cout << "out of space" << endl;
H->Capacity = MaxElements;
H->Size = 0;
H->Elements[0] = MinData;
for(int i = 1; i <= H->Capacity; ++i)
{
H->Elements [i] = 0; //全部幅值为0
}
return H;
}
void Destroy(PriorityQueue H) //释放一个优先列队
{
free(H->Elements);
free(H);
}
void MakeEmpty (PriorityQueue H)
{
for(int i = 1; i <= H->Capacity; ++i)
{
H->Elements[i] = 0;
}
H->Size = 0;
}
bool IsEmpty (PriorityQueue H)
{
if(H->Size == 0)
return true;
else
return false;
}
bool IsFull (PriorityQueue H)
{
if(H->Size == H->Capacity )
return true;
else
return false;
}
void Insert(int Key,PriorityQueue H)
{
int i;
if(IsFull(H))
{
cout << "Priority queue is full" << endl;
return;
}
//优先列队的队首元素一定为最下元素,插入时先在最后创建一个空穴,在把这个空穴上滤
//对于优先列队的任意位置i的元素,他的左儿子在2i处,右儿子在2i+1出,父亲在i/2向下取整处
for (i = ++H->Size; H->Elements[i/2] > Key; i /= 2)
H->Elements[i] = H->Elements[i/2];
H->Elements[i] = Key;
}
int DeleteMin(PriorityQueue H)
{
int i, Child;
int MinElement, LastElement;
if(IsEmpty(H))
{
cout << "Priority queue if Empty" << endl;
return H->Elements[0];
}
MinElement = H->Elements[1];
LastElement = H->Elements[H->Size--];
//思想很巧妙,空穴从最低一个位子一直下滤
for(i = 1; i * 2 <= H->Size; i = Child)
{
//寻找小的儿子
Child = i * 2;
if(Child != H->Size && H->Elements[Child + 1] < H->Elements[Child])
Child ++;
if(LastElement > H->Elements[Child])
H->Elements[i] = H->Elements[Child];
else
break;
}
H->Elements[i] = LastElement;
return MinElement;
}
int main ()
{
PriorityQueue H = Init_priorityqueue(11);
Insert(16, H);
Insert(26, H);
Insert(13, H);
Insert(14, H);
Insert(19, H);
Insert(69, H);
Insert(32, H);
Insert(21, H);
Insert(31, H);
for (int i = 0; i <= 9; ++i)
{
cout << DeleteMin(H) << endl;
}
return 0;
}
因为二叉堆的堆序性,所以可以用来排序,即堆排序,以后会具体论述。
夜深了,,,
从未提起,从未忘记。
浙公网安备 33010602011771号