数据结构----堆(2)

堆1中介绍了堆的定义性质以及建堆过程,这篇主要介绍堆排序以及堆的一种应用---优先级队列

1、堆排序

堆排序算法,先用build_max_heap将输入数组A[0,...,n-1]建立一个最大堆。因为数组中最大元素在A[0],则可以通过交换A[0]和A[n-1],此时将最大数A[n-1]存入结果数组result中,并将此节点去掉,此时数组就剩下A[0,...,n-2],由于互换,新的根元素可能违背了最大堆的性质,此时再调用建堆子程序Max_heapify(A,0)保持此性质,在A[0,...,n-2]中构造最大堆。不断递归这个过程,堆的大小从n-1降到1。c语言程序如下://堆排序

void heap_sort(int nums[],int len){
    //首先建一个大根堆
	build_max_heap(nums,len);
	int *result = new int[len];//存放排好序的数组

	for(int i=len-1;i>=1;i--){
	    *result++=nums[0];//最大数一直在根上,赋值 后,移除最大元素
		nums[0]=nums[i];//从最后一个元素开始遍历,将其移到根部,并执行保持最大堆子程序,找到去除最大元素的次大元素,以此类推
		max_heapify(nums,i,0);
	}
	*result=nums[0];

}

分析此算法:建堆运行时间O(n),循环n-1次,每次循环中执行O(log2^n)+c,因此总的运行时间为O(n)+(n-1)(O(log2^n)+c)=O(nlog2^n)

2、堆的一种应用---优先级队列

优先级队列是一种用来维护一组元素构成的集合S的数据结构,每一个元素有一个关键字key。分为最大优先级队列和最小优先级队列。一个最大优先级队列支持一下操作:

(1)maximum(S):返回S中最大关键字的元素

(2)extract_max(S):去掉并返回S中最大关键字的元素

(3)increase_key(S,x,k):将元素x的关键字的值增加到k,这里k值不能小于x的原关键字的值

(4)insert(S,x):将元素x插入集合S

最大优先级队列的一个应用是一台分时计算机上进行作业调度。队列对要执行的作业以及优先级进行记录并调度。当一个作业完成时或者中断时,可用extract_max操作从所有等待的作业中,选出一个优先级最高的作业来执行。

优先级队列可以用堆来实现。

几个操作实现如下:

 

//返回nums中具有最大关键字的元素
int maximum(int nums[],int len){
    return nums[0];
}
//去掉,并返回nums中具有最大关键字的元素
int  extract_max(int nums[],int len){
    if(len<1){
	   cout<<"error:heap underflow"<<endl;
	}
	int max=nums[0];
	nums[0]=nums[len-1];
	nums[len-1]=NULL;
	max_heapify2(nums,len-1,0);
	return max;
}
//将nums[index]的关键字的值增加到key,增加后将其移到合适的位置,使其满足最大堆
void increase_key(int nums[],int len,int index,int key){
	if(key<nums[index]){
	   cout<<"error:new key is smaller than current key"<<endl;
	}
	nums[index]=key;
	int parent_index=(index-1)/2;
	int temp=0;
	while(index>=0&&nums[index]>nums[parent_index]){//类似插入排序
	     temp=nums[index];
		 nums[index]=nums[parent_index];
		 nums[parent_index]=temp;
		 index=parent_index;
		 parent_index=(index-1)/2;
	}
  
}
//将x插入最大堆的适合位置,首先加入负无穷的叶子节点,然后调用increase_key()设置新节点的值并移到合适位置
void insert(int nums[],int len,int x){
   int key=INT_MIN;
   nums=(int *)realloc(nums,len+1);
   nums[len]=key;
   increase_key(nums,len+1,len,x);
}

 分析四种操作:第一种操作:O(1)第2、3、4操作:O(log2^n)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值