码迷,mamicode.com
首页 > 其他好文 > 详细

优先队列及其基本操作的堆实现

时间:2015-08-07 22:30:28      阅读:200      评论:0      收藏:0      [点我收藏+]

标签:

用代码说话

/*
	本代码实现优先队列:分为最大优秀队列和最小优先队列
	优先队列用于维护一组元素构成的集合S的数据结构,其中的
	每一个元素都有一个相关的值,称为关键字。
	一个最大优先队列支持以下操作:
		insert(S,x)向S中插入元素x;
		maximum(S)返回S中的最大键值元素;
		extract-max(S)去掉并且返回S中的最大键值元素;
		increase-key(S,x,k)将元素x的关键字增加到k,假设k要不小于x的原关键字

	一个最小优先队列支持以下操作:
		insert(S,x)向S中插入元素x;
		minimum(S)返回S中的最小键值元素;
		extract-min(S)去掉并且返回S中的最小键值元素;
		decrease-key(S,x,k)将元素x的关键字减小到k,假设k要不大于x的原关键字

	最大优先队列可以应用与操作系统的作业调度
	最小优先队列可以用于基于事件驱动的模拟器
	本文将实现最大优先队列
	优先队列可以用堆来实现
*/

#include<stdio.h>
#include<stdlib.h>
#define N 6

static int heapSize=N;
/*
    返回父节点和子节点索引
*/
//返回父结点
int parent(int index)
{
    return (index-1)/2;
}
 
//返回左孩子
int left(int index)
{
    return (index<<1)+1;
}
 
//返回右孩子
int right(int index)
{
    return (index+1)<<1;
}

/*
    维护堆的性质,即把不符合要求的元素重新组织
    时间复杂度为logn
*/
int maxHeapify(int *A,int index,int size)
{
    int L=left(index);
    int R=right(index);
    int tmp;
    int largestIndex;
    if(L<size && *(A+index)<*(A+L)) {
        largestIndex=L;
    } else {
	largestIndex=index;
    }
    if(R<size && *(A+largestIndex)<*(A+R)) {
        largestIndex=R;
    }
    if(index!=largestIndex) {
        tmp=*(A+index);
        *(A+index)=*(A+largestIndex);
        *(A+largestIndex)=tmp;
        maxHeapify(A,largestIndex,size);
    }
    return 0;
}

/*
    对除没有子结点的结点进行堆的维护操作,进而
    使得一个数组变成一个最大堆
    时间复杂度为nlogn
*/
int buildMaxHeap(int *A)
{
    int size=N;
    //找出不是叶子结点的最后一个索引
    int need=heapSize/2-1;
    int i;
    for(i=need;i>=0;i--) {
        maxHeapify(A,i,heapSize);
    }
    return 0;
}

/*
    堆排序程序
    通过根元素始终是最大的,因此我们倒过来找
    从最大的元素依次往最小的元素去排序
*/
int heapSort(int *A)
{
    buildMaxHeap(A);
    int j;
    int size=heapSize;
    int i;
    int tmp;
    for(i=N-1;i>=1;i--) {
        tmp=*A;
        *A=*(A+i);
        *(A+i)=tmp;
        size--;
        maxHeapify(A,0,size);
    }
    return 0;
}

//------------------以下为优先队列的操作-----------------------//

/*
	返回堆的最大值
*/
int heapMaxElement(int *A)
{
	return A[0];
}

/*
	获取堆的最大值并移除该最大值
*/
int heapExtractMax(int *A)
{
	if(N<1) {
		printf("Heap error!");
	}
	int max=heapMaxElement(A);
	A[0]=A[heapSize-1];
	heapSize=heapSize-1;
	maxHeapify(A,0,heapSize);
	return max;
}

/*
	增加第i个元素的值,然后重新构建堆
*/
int heapIncreaseKey(int *A,int index,int newValue) 
{
	if(newValue<*(A+index)) {
		printf("新增加的值应该要比原值大!");
		return 1;
	}
	*(A+index)=newValue;
	while(index>0&&*(A+index)>*(A+parent(index))) {
		int temp;
		temp=*(A+index);
		*(A+index)=*(A+parent(index));
		*(A+parent(index))=temp;
		index=parent(index);
	}
	return 0;
}

/*
	向最大堆中插入元素
*/
int heapInsert(int *A,int key)
{
	heapSize=heapSize+1;
	int *b=malloc(sizeof(int)*heapSize);
	b=A;
	*(b+heapSize-1)=key-1;
	heapIncreaseKey(b,heapSize-1,key);
	A=b;
	return 0;
}

int main()
{
	int b[N]={2,1,3,2,5,4};
	int* a=b;
	//必做:构建最大堆
	buildMaxHeap(a);
	printf("增加第一个元素的值为6\n");
	heapIncreaseKey(a,0,6);
	printf("%d\n",*a); 

	printf("向堆中插入7\n");
	heapInsert(a,7);
	printf("%d\n",*a); 

	printf("输出顶部元素\n");
	printf("%d\n",*a);

	printf("弹出顶部元素\n");
	printf("%d\n",heapExtractMax(a));

	printf("输出顶部元素\n");
	printf("%d\n",*a);
	
	return 0;
}

运行结果


zzw@zzw-ThinkPad-Edge-E430c:~/Algorithms/chap6/demo1$ ./priorityQueue 
增加第一个元素的值为6
6
向堆中插入7
7
输出顶部元素
7
弹出顶部元素
7
输出顶部元素
6



优先队列及其基本操作的堆实现

标签:

原文地址:http://my.oschina.net/zzw922cn/blog/489349

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!