排序算法总结归纳 之 插入排序

按照排序的数据量的大小,一般将排序方法分为内排序和外排序。
内排序是指待排序的数据元素都存放在内存中,而外排序则指待排序的数据量太大,不能同时存放在内存中,整个排序过程需要在内外存之间多次交换才能进行。
常用的内排序算法有:插入排序、选择排序、交换排序、归并排序和基数排序等。而外排序算法则有多路平衡归并排序和最佳归并树。
1.插入排序
基本思路:从初识有序的子集合开始,不断地把新的元素插入到有序的子集合中合适的位置,使有序子集合中数据元素的个数不断增加,直到有序子集合的大小等于待排序的数据元素集合的大小为止。
常见的插入排序方法有:直接插入排序和希尔排序。
直接插入排序
基本思路:顺序地把待排序的数据元素按其关键字值的大小插入到已排列有序的子集合的适当位置,子集合的数据元素的个数逐渐增大,直至有序子集合的大小等于待排序元素集合的大小为止。
构造一个初识的有序子集合。方法:将第一个元素看成是初识有序子集合,然后从第二个元素开始,依次将其插入到有序子集合中去。
算法描述如下:

void InsertSort(ElemType A[], int n)
{  //采用直接插入排序法对A[0]~A[n-1]
	int i,j;
	ElemType temp;
	for(i=1;i<n;i++)
	{
		temp = A[i];
		j=i-1;
		while(j>-1&&temp.key<A[j].key)//内部排序
		{
			A[j+1]=A[j];//把关键字值大的元素放在后面
			j--;
		}
		A[j+1]=temp;
	}
}

时间复杂度:O(n^2),空间复杂度:O(1)只使用一个临时工作单位temp
希尔排序
基本思想:先把待排序的元素序列分成若干个小组,对同一组内的元素分别进行直接插入排序,然后,小组内元素个数逐渐增加,小组的个数据逐渐减少,当完成了所有数据元素都在同一个组内的排序后排序过程结束。
如何分割待排序的元素:“跳跃分割”,将相距某个“增量”的元素分在同一个小组内,确保全局基本有序而不是局部有序。
如何确定“增量”:一般的原则是,开始是增量取值较大,使得每个小组内的元素个数较少,这样提供了元素跳跃移动的可能性,效率较高;后来增量逐步减少,每个小组中的元素个数逐步增加,但基本有序。希尔最早提出的方法是di=Math.floor([n/2]),d(i-1)=Math.floor([di/2]),且为质数,并且最后一个增量必须等于1。
算法描述如下:

void ShellSort(ElemType A[], int d[], int num)
{//采用希尔排序法对A[0]~A[n-1]排序,d[0] ~ d[num-1]为增量序列。
	int i,j,k,m,span;
	ElemType temp;
	for(m=0;m<num;m++)
	{
		span = d[m];
		for(k=0;k<span;k++)
		{
			for(i=k+span;i<n;i+=span)
			{
			temp=A[i];
    			j=i-span;
    			while(j>-1&&temp.key<A[j].key)
    			{
    				A[j+span]=A[j];
    				j-=span;
    			}
		}
			A[j+span]=temp;
		}
	}
}

希尔排序算法的空间复杂度为O(1),时间复杂度在O(nlog2n)和O(n^ 2)之间,最好的情况达O(n^ 1.3)。

猜你喜欢

转载自blog.csdn.net/qq_42314621/article/details/84993682