【排序篇1】插入排序、希尔排序

目录

    • 一、插入排序
    • 二、希尔排序

一、插入排序

思路:
插入排序就像玩扑克牌,抽出一张牌作为比较的元素,与前面的牌依次进行比较,小于继续往前比较,大于等于停下插入到当前位置。

图示:
【排序篇1】插入排序、希尔排序_第1张图片

void InsertSort(int* a, int n)
{
	//控制所有次排序
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;//记录临时下标
		int tmp = a[end + 1];//比较的元素
		//一趟排序
		while (end >= 0)
		{
			if (a[end] > tmp)//非升序
			{
				a[end + 1] = a[end];//前面的覆盖后面的
			}
			else
			{
				break;//是升序跳出本次循环
			}
			--end;//下标往前移动
		}
		a[end + 1] = tmp;//指向元素的下一个元素覆盖为tmp
	}
}

注意:总共的排序次数是n-1趟,即end最多只能到倒数第二个元素,因为如果end为最后一个元素,那么end+1的位置就是越界的。

特性总结:

  • 数组的元素越接近有序,该排序的效率越高
  • 时间复杂度:O(N^2)
  • 空间复杂度:O(1)
  • 稳定

二、希尔排序

希尔排序与插入排序很像,单趟排序的思路基本相似,不同的是,插入排序的每次对比一个指向的元素是向前移动一个距离,希尔排序是移动gap个距离,从大到小,最后为1

【排序篇1】插入排序、希尔排序_第2张图片

void ShellSort(int* a, int n)
{
	int gap = n;//先定义好初始距离
	while (gap > 1)//限定条件
	{
		gap = gap / 3 + 1;//距离缩小
		//类似插入排序,只是把1改成gap
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (a[end] > tmp)
				{
					a[end + gap] = a[end];
				}
				else
				{
					break;
				}
				end -= gap;
			}
			a[end + gap] = tmp;
		}
	}
}

注意:while循环的条件gap大于1并不是说gap不能为1,而是这里在前面的进入循环的时候就有可能为1了,记住gap是先缩小再使用的,进入循环时(还没有缩小)的gap是上次使用的gap

假如gap此时为2:,满足条件,进入while循环,2除3等于0,0加1等于1,下面使用的gap就是1

再进行循环的判断,如果条件不是大于1的话,而是大于等于1,那么gap为1可以进入循环,然后1除1等于1,1+1等于2,就死循环了。

特性总结:

  • 希尔排序是对直接插入排序的优化
  • 希尔排序的时间复杂度不好计算,因为gap的取值方式很多,时间复杂度暂时为:O(N ^1.3)——O(N ^2)
  • 空间复杂度:O(1)
  • 不稳定

你可能感兴趣的:(数据结构初阶,排序算法,算法,数据结构,开发语言,c++)