最小优先队列的可以实现的操作:
insert,插入一个元素
min,找到最小的元素
extract-min,去掉最小的元素并返回最小的元素
increase-key,增加一个关键字的值
优先队列的形式是一个堆。也就是有parent,left,right和自身的值的形式。实现他的操作是依赖于堆的操作,比如要插入一个key,实际上就是在堆中去找key的位置,然后维护堆。所以要时刻清醒的是现在的堆是一种什么形式,输出这个优先队列只是把堆按照数组的形式输出来了,本质上是在输出堆。
#include "stdafx.h"
#include<stdio.h>
#include <limits.h>
//最小堆实现最小优先序列
void swap(int *x, int *y) //用作交换值的函数
{
int t;
t = *x;
*x = *y;
*y = t;
}
int parent(int i) //计算关系结点编号
{
return i / 2;
}
int left(int i)
{
return 2 * i;
}
int right(int i)
{
return 2 * i + 1;
}
void minheap(int a[], int i,int truesize) //维护最xiao堆性质
{
int smallest; //储存最xiao结点编号
int l; //左结点
int r; //右
l = left(i);
r = right(i);
if (a[l - 1] < a[i - 1] && l <= truesize) //注意 C语言数组下标应该将i-1
smallest = l;
else
smallest = i;
if (a[r - 1] < a[smallest - 1] && r <= truesize)
smallest = r;
if (smallest != i)
{
swap(&a[smallest - 1], &a[i - 1]); //逐层维hu
minheap(a, smallest,truesize);
}
}
void buildminheap(int a[],int truesize) //建立最xiao堆
{
int n = truesize;
int i;
for (i = n / 2; i > 0; i--)
{
minheap(a, i,n);
}
}
void heapsort(int a[],int truesize) //堆排序,从大到小输出
{
int i =truesize;
for (; i>0; i--)
{
swap(&a[i - 1], &a[0]);
truesize--;
minheap(a, 1,truesize);
}
}
int heap_min(int a[],int n)
{
return a[0];
}
int heap_extract_min(int a[],int n)
{
if (n < 1)
return 0;
int min = a[0];
a[0] = a[n - 1];
n--;
minheap(a,1,n);
return min;
}
int heap_increase_key(int a[], int i, int key)
{
if (key > a[i])
{ //当key>parent 的时候终止
return 0;
}
a[i] = key;
while (i > 0 && a[parent(i)] > a[i])
{
swap(&a[i], &a[parent(i)]);
i = parent(i);
}
}
void min_heap_insert(int a[], int key,int n)
{
n++;
a[n - 1] = 100000; //插入后的位置预置为正无穷
heap_increase_key(a, n-1, key);
}
int main()
{
int a[10] = { 4,1,3,2,16,9,10,14,8,7 };
int i,n=10;
printf("\n堆中的元素是------------------\n");
for (i = 0; i < n; i++) //输入堆中元素
printf("%d ", a[i]);
printf("\n最小堆------------------\n");
buildminheap(a,n); //建立最xiao堆
for (i = 0; i < n; i++)
printf("%d ", a[i]); //输出
/* heapsort(a,n); //堆排序
printf("\nresult------------------\n");
for (i = 0; i < n; i++)
printf("%d ", a[i]); //输出结果
*/
heap_min( a,n);
heap_extract_min(a,n);
printf("\n调用extract后的最小堆:\n");
for (i = 0; i < n-1; i++)
printf("%d ", a[i]); //输出结果
printf("\n");
min_heap_insert(a, 5, n-1); //插入5
printf("插入后的最小堆\n");
for (i = 0; i < n; i++)
printf("%d ", a[i]); //输出结果
printf("\n插入后的堆排序\n");
heapsort(a, n);
for (i = 0; i < n; i++)
printf("%d ", a[i]); //输出结果
return 0;
}
因为我一开始没有理解上面我所说的,队列的操作都是在操作堆,所以理解上出现了问题。在输出最小值的时候,我先用了heapsort进行堆排序然的
就觉得最小值应该是数组中的最后一个。把堆按sort输出了这样其实是没错的,但是到下面就出现问题了。extract_min一直是对一个最小堆在操作的,当你把你的最小堆sort成一个递减的数组的数组的时候,进行的操作是把堆顶元素与最后一个元素互换,然后把堆里的元素减少1,再把最后一个元素输出,最后一个元素即堆顶元素一定是当前的最小值,继续维护最小堆,重复这个过程。在这个过程中堆里的元素已经在减少了,最后堆已经没了。然后再去进行extract等一系列操作就不是在原来最小堆的基础上操作了。。。