程序猿找工作必练内功:排序算法大总结(三)——堆排序算法

堆排序算法依靠堆的性质来达到排序的目的,此处的堆不同于程序中的堆,此处的堆的逻辑形态是一棵完全二叉树,树根的值大于左右孩子的值,子树也满足这个性质,这样的堆称为大顶堆,反之成为小顶堆。因此堆顶的元素就是最大或最小的元素。因此,给定一个有n个元素的序列,就可根据堆的形态和性质把序列调整为一个堆,然后交换堆的堆顶元素和堆的最后元素,再对长度为n-1的序列进行堆调整,直到序列长度为1,此时序列已排好序。时间复杂度是O(nlgn),空间复杂度O(1)。

利用堆,还可以实现优先队列,依据优先级的高低来建堆,堆顶元素就是最大优先级或最小优先级。我的csdn资源里有我的一个实现。

另外,对于找出海量数据的前N大元素或前N小元素,堆提供了一个可行的解决方案。如果是找出前N大元素,可以先读取N个元素建成一个最小堆,然后一次读取一个元素,与堆顶元素比较,如果大于堆顶元素,则替换掉堆顶元素,再调整成新的堆,直至所有元素读取完毕,最后堆里的元素就是要求的答案。如果是找出前N小元素,则建大顶堆,其余操作一样。这种方法对机器的内存要求很低,因此可用来处理海量数据。我的csdn资源里有这种方法的实现。

下面给出堆排序的实现代码:

//MaxHeap.hpp

#ifndef MAXHEAP_H
#define MAXHEAP_H

/************最大堆************/
//堆调整
template<class type>
void maxHeapify(type *A, int i, int n)
{
	type key = A[i];
	for (int k=2*i+1; k<n; k=2*i+1)//k为左孩子
	{
		if (k+1<n&&A[k]<A[k+1])//k+1是右孩子,一定要加k+1<n,找出左右孩子中的最大值
			k++;
		if (key<A[k])
		{
			A[i] = A[k];
			i = k;
		}
		else     //根最大,不用再调整
			break;
	}
	A[i] = key;
}
//建堆
template<class type>
void buildMaxHeap(type *A, int n)
{
	if (!A)
		return;
	for (int i=n/2 - 1; i>=0; i--)//从第一个有孩子的元素开始调整,下标是n/2-1
		maxHeapify<type>(A, i, n);
}

#endif 

//HeapSort.hpp

#ifndef HEAPSORT_H
#define HEAPSORT_H

#include <algorithm>
using namespace std;

#include "MaxHeap.hpp"

//堆排序
void heapSort(int *A, int n)
{
	if (!A)
		return;
	buildMaxHeap<int>(A, n);
	for(int i=n-1; i>0; i--)
	{
		swap(A[i], A[0]);
		maxHeapify<int>(A, 0, i);
	}
}
#endif



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值