排序算法之堆排序

 堆排序>

    在上一篇中提到了大小堆的问题,大小堆的一个应用就是堆排序,那仫什仫是堆排序呢?相对于我们经常使用的冒泡,选择以及直接插入排序,堆排序又存在什仫样不同的地方?我就从这几个问题开始着手解决堆排序的问题.

    堆排序顾名思义就是利用堆(假设利用小堆)进行排序的方法,它的基本思想是:先将待排序的序列构成一个小堆,在这个时候堆顶结点就是整个系列的最小值;然后将堆顶元素与堆数组末尾的元素交换,此时末尾的元素就是最小值;最后将剩余的n-1个序列重新构造成一个小堆,和第二步的实现类似,这个时候就会得到n个元素的次小值,这样一直到根结点就能得到一个有序的序列了.

 

    (1).堆排序的方法实现升序序列要构造的是大堆

    (2).堆排序的方法实现降序排列要构造的是小堆

  

      我们知道建堆的时间复杂度为O(n*lgn).

      在正式排序时第i次取堆顶元素然后重新构造堆的时间复杂度为O(lgi),而且需要取n-1次堆顶记录,所以重建堆的时间复杂度为O(n*logn).

      总的来说堆排序的时间复杂度为O(n*logn).

      因为堆排序对原始记录的排序状态并不敏感,不管是在最好还是最坏和平均时间复杂度上都是O(n*logn),这在性能上远远高于冒泡,选择和插入的时间复杂度O(n^2)了.

       在空间复杂度上,因为它始终只有一个用于交换的空间所以是O(1),但是因为是跳跃式的比较和交换,所以堆排序相对于冒泡,选择和直接插入排序这些稳定的排序算法来说是一种不稳定的排序算法

       用仿函数的方法解决升序和降序代码复用性的问题:

       

#include<iostream>
#include<vector>
#include<cassert>
using namespace std;

template<class T>
struct SortUp
{
	//升序
	bool operator()(const T& l,const T& r)
	{
		return l < r;
	}
};

template<class T>
struct SortDown
{
	//降序
	bool operator()(const T& l,const T& r)
	{
		return l > r;
	}
};
//利用仿函数的特性解决代码的复用性,默认升序排列.
template<class T,class Compare=SortUp<T>>
class HeapSort
{
public:
	void Sort(int a[],int size)
	{
		assert(a);
		//先建造一个堆,从倒数第一个非叶子结点开始调整
		for(int i=(size-2)/2;i>=0;--i)
		{
			_AdjustHeap(a,size,i);
		}
		int end=size-1;
		while(end > 0)
		{
			swap(a[0],a[end]);
			_AdjustHeap(a,end,0);
			--end;
		}
	}
	void Display(int a[],int size)
	{
		for(int i=0;i<size;++i)
		{
			cout<<a[i]<<" ";
		}
		cout<<endl;
	}
protected:
	void _AdjustHeap(int a[],int size,int root)
	{
		int parent=root;
		int child=2*parent+1;
		while (child < size)
		{
			Compare com;
			if (child+1 < size
				&& com(a[child],a[child+1]))
			{
				child++;
			}
			if (com(a[parent],a[child]))
			{
				swap(a[child],a[parent]);
				parent=child;
				child=2*parent+1;
			}
			else
				break;
		}
	}
};

void testHeapSort()
{
	int array[]={10,16,18,12,11,13,15,17,14,19};
	int size=sizeof(array)/sizeof(array[0]);
	//测试升序
	HeapSort<int,SortUp<int>> hs1;
	hs1.Sort(array,size);
	hs1.Display(array,size);
	//测试降序
	HeapSort<int,SortDown<int>> hs2;
	hs2.Sort(array,size);
	hs2.Display(array,size);
}



 

   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值