【Sort1】直接插入排序和希尔排序

版权声明:本文为博主原创文章,欢迎转载,转载请声明出处! https://blog.csdn.net/hansionz/article/details/82630897
一.直接插入排序

单独总结我的另一篇博客:
https://blog.csdn.net/hansionz/article/details/80835834

  • 代码实现
//直接插入排序
int InsertSort(int *num,int len)
{
	assert(num);
	int i = 0;
	//第一个元素已经为有序序列,所以要进行len-1次排序
	for (; i < len - 1; i++)
	{
		int end = i;
		int tmp = num[i + 1];//保存非有序区间第一个元素,否则在后边的移动中会改变
		//比较后移
		while (end >= 0 && num[end]>tmp)
		{
			num[end+1] = num[end];
			--end;
		}
		//插入到适当位置
		num[end + 1] = tmp;
	}
}
  • 时间复杂度:最优情况,待排序序列接近有序,要移动的关键字只有常数次,它的时间复杂度为O(N);最坏情况,待排序列基本无序,时间复杂度为O(N*N)
  • 空间复杂度:只开辟了tmp一个空间,所有空间复杂度为O(1)
二.希尔排序
1.什么是希尔排序?

希尔排序又叫缩小增量排序,它实质上是一种插入排序。一方面,它的发现者DL.Shell是基于在我们进行直接插入排序的过程中有的记录移动的太慢了而且移动的次数很大,那能不能想办法让它移动的快一点呢?于是DL.Shell想到让记录按下标的一定增量分组,对每组使用直接插入排序算法排序,最后在进行一次直接插入排序。另一方面,希尔排序是对直接插入排序的优化,它先进行预排序,使得待排序列基本有序,在进行直接插入排序O(N),所以它主要分为两步

  • 预排序(预排序之后使得要排序序列接近于有序)
    这里写图片描述
    它让记录中大的数字较快的移动到后边,主要是基于这样的想法,让整个记录序列基本有序。
    注:图片借用Prepare_y博主博客中的图片
  • 直接插入排序:最后一次排序gap必须等于1,基本有序的记录序列进行一次直接排序得到最终排序结果
2.代码实现
//希尔排序(缩小增量排序)
/*最好步长序列是由Sedgewick提出的(1, 5, 19, 41, 109,...)*/
int ShellSort(int *num, int len)
{
	assert(num);

	int gap = 5;//步长

	//最后一次步长必须为1
	while (gap >= 0)
	{
		//1.gap>1时预排序
		for (int i = 0; i < len - gap; i++)
		{
			int end = i;
			int tmp = num[end + gap];
			while (end >= 0 && num[end] > tmp)
			{
				num[end + gap] = num[end];
				end -= gap;
			}
			num[end + gap] = tmp;
		}
		gap -= 2;
	}
	//2.gap为1时直接插入排序(这时要排序序列已经接近有序)
}
3.效率分析

希尔排序是基于多次预排序让记录中大的数字较快的移动到后边,使得记录序列基本有序,而不是像直接排序中一个一个往后移动。总的来说希尔排序的效率肯定比直接插入排序要高。因为希尔排序的时间复杂度和它的步长选择有关系,它的平均时间复杂度为n*log(n)。另外,由于排序序列中数据的相对位置可能变化,所以希尔排序是一种不稳定的排序

猜你喜欢

转载自blog.csdn.net/hansionz/article/details/82630897