插入排序:直接插入排序 希尔排序

插入排序:

假设红竖线前的元素全部排好序,红线后面的数即为要插入的数据,红线依次往后移,假设end为排好序的最后一个数字,end+1即为要插入的数字,一次插入时,end与要插入的数字依次比较,之后end--,直到end小于0后循环停止,进入下一次的插入数据,故让end等于for循环里的i即可,一次插入之后end就向后移一位,循环次数为n-2(若为n-1,end+1就会越界)。

插入排序:直接插入排序 希尔排序_第1张图片

//插入排序,以升序为例
//时间复杂度为O(N^2)
//逆序的情况最坏(最坏的情况下的次数为时间复杂度e)
void InsertSort(int* a, int n)//n为数组元素的个数
{
	//[0,end]有序,end+1位置的值插入[0,end],让[0,end+1]有序。
	//控制循环次数,防止数组越界
	for (int i = 0; i < n-1; i++)
	{
		int end = i;
		//记录end+1处的值,防置被覆盖之后找不到原始数据
		int temp = a[end + 1];
		while (end >= 0)
		{
			if (a[end] > temp)
			{
				a[end + 1] = a[end];
				end--;
			}
			else
				break;
		}
		a[end + 1] = temp;
	}
}

 希尔排序:

插入排序:直接插入排序 希尔排序_第2张图片

希尔排序是将数组里的元素间隔为gap的数据分为一组,将本组的数据排序,如上图,此时1 4 7 0为一组,2 5 8为一组,3 6 9为一组,分别将每组进行排序,最后会得到相比原来较为有序的数组,其算法和插入排序类似,只是每次分组并排序后的gap会越来越小,直到为1,就是直接插入排序。总体来说,希尔排序是将数组变为接近有序的数组,然后再进行直接插入排序,这样大大提高了代码效率。

  • 多组间隔为gap的预排序,gap越大,大的数可以越快的到后面,小的数可以越快的到前面,
  • gap越大,预排完越不接近有序,
  • gap越小越接近有序
  • gap=1时,就直接是插入排序
//希尔排序
//直接插入排序的优化
//1.先对数组进行预排序,使数组接近有序     //预排序:分组排序,间隔为gap为一组,gap是几就分成几组
//2.直接插入排序
//平均时间复杂度:O(N^1.3)
void ShellSort(int* a, int n)
{
	int gap=n;
	while (gap > 1)
	{
		gap = gap / 2;//时间复杂度为log以2为底N的对数
		//gap很大时,预排序时间复杂度为O(N)
		//gap很小时,此时数组已经接近有序,时间复杂度可近似看成O(N)
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int temp = a[end + gap];
			while (end >= 0)
			{
				if (a[end] > temp)
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
					break;
			}
			a[end + gap] = temp;
		}
	}
}

你可能感兴趣的:(算法,数据结构,排序算法)