常用的排序算法分析

 
//插入排序 将P位置的元素插到前P+1个元素中的正确位置,保证在P位置的时候前面的
//的元素是处于排序状态
//时间复杂度O(N*N)的时间界
template<class Comparable>
void insertionSort(vector<Comparable>& a)
{
	int j;
	for(size_t p = 1;p < a.size();p++)
	{
		Comparable temp = a[p];
		for(j = p;j > 0 && temp < a[j-1];j--)
			a[j] = a[j-1];
		a[j] = temp;
	}
}


插入排序是最容易理解的

//shell排序 保证h(k)排序性
//缩减增量排序
template<class Comparable>
void shellsort(vector<Comparable>& a)
{
	for(int gap = a.size()/2;gap > 0;gap /= 2)//shell 增量
	{	
		for(size_t i = gap;i < a.size();i++)
		{
			Comparable temp = a[i];
			int j = i;
			for(;j >= gap && temp < a[j-gap];j -= gap)
				a[j] = a[j-gap];
			a[j] = temp;
		}
	}
}

shell排序的理论证明非常困难,不过它的意思还是很简单的,实际上它是插入排序的进化版本,它最坏情况下的是运行时间是 亚N^2

如何理解这个排序算法,不防只看内部两层循环,是不是和插入排序很像?只是步长不同,shell排序是以增量的步长来插入的,它将位置i的元素插入到i,i-gap,i-2*gap...组成的序列中的正确位置当中。

 

//堆排序
//利用二叉堆的堆序性质
inline int leftchild(int i)
{
	return i * 2 + 1;
}
template<class Comparable>
void percolatedown(vector<Comparable>& a,int i,int n)	//数组,下滤的空穴位置,边界范围
{
	int child;
	Comparable temp;
	for(temp = a[i];leftchild(i) < n;i = child)
	{
		child = leftchild(i);
		if(child != n - 1 && a[child] < a[child + 1])
			child++;
		if(temp < a[child])
			a[i] = a[child];
		else
			break;
	}
	a[i] = temp;
}
template<class Comparable>
void heapsort(vector<Comparable>& a)
{
	for(int i = a.size()/2;i >= 0;i--)
		percolatedown(a,i,a.size());
	for(int j = a.size()-1;j > 0;j--)
	{
		swap(a[0],a[j]);
		percolatedown(a,0,j);
	}
}

堆排序是相对插入排序来说第二简单的算法,它的理论来源于二叉堆,二叉堆的插入时间为O(logN),那么总的时间是N*logN

//归并排序 采用分治策略
template<class Comparable>
void merge(vector<Comparable>& a,vector<Comparable>& tempArray,int leftpos,
		   int rightpos,int rightend)		//归并函数,将两个排好序的数组合并
{
	int leftend = rightpos - 1;
	int temppos = leftpos;
	int numelements = rightend - leftend + 1;
	//
	while(leftpos <= leftend && rightpos <= rightend)
		if(a[leftpos] <= a[rightpos])
			tempArray[temppos++] = a[leftpos++];
		else
			tempArray[temppos++] = a[rightpos++];
	while(leftpos <= leftend)
		tempArray[temppos++] = a[leftpos++];
	while(rightpos <= rightend)
		tempArray[temppos++] = a[rightpos++];
	for(int i = 0;i < numelements;i++,rightend--)
		a[rightend] = tempArray[rightend];
}
template<class Comparable>
void mergesort(vector<Comparable>& a,vector<Comparable>& tempArray,
			   int left,int right)	//分治函数 运用递归思想进行分治
{
	if(left < right)
	{
		int center = (left + right) / 2;
		mergesort(a,tempArray,left,center);
		mergesort(a,tempArray,center + 1,right);
		merge(a,tempArray,left,center + 1,right);
	}
}
template<class Comparable>
void mergesort(vector<Comparable>& a)
{
	vector<Comparable> tempArray(a.size());	//临时数组 用于归并
	mergesort(a,tempArray,0,a.size() - 1);
}


归并算法也是很容易理解的一个算法,是分治策略运用的经典例子。不断的划分子数组一直到不能划分为止,然后合并。它的时间复杂度下界为O(N*logN),缺点就是需要线性的附加内存,需要借助临时数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值