个人主页:Lei宝啊
愿所有美好如期而遇
这两个排序在思路上有些相似,所以有人觉得插入排序和希尔排序差别不大,事实上,他们之间的差别不小,插入排序只是希尔排序的最后一步。
目录
当我们有了一个有序的数组arr,假设为升序,现在向里面插入一个新数据。
我们假设这个数组有n个元素,最后一个元素的下标我们记作end,那么要插入的这个数下标为end+1,并用tmp记下这个数的大小。
接下来,如果tmp小于arr[end],那么arr[end+1] = arr[end]; end--,
如果tmp大于等于arr[end],那么break; arr[end+1] = tmp;
重复上述操作,直到end < 0或者break跳出
那么面对一个无序的数组,我们可以将第一个元素当做有序,第二个元素为新插入元素,依次类推排序

- void InsertSort(int* arr, int n)
- {
-
- //i == n - 2时,temp = arr[n - 1];
- for (int i = 0; i < n - 1; i++)
- {
- int end = i;
- int temp = arr[end + 1];
-
- //此处画个图,end小于0跳出循环
- while (end >= 0)
- {
- if (temp < arr[end])
- {
- //插入的值比end小,end值向后移动一位
- arr[end + 1] = arr[end];
- end--;
- }
- else
- {
- break;
- }
-
- }
- //写在循环外的原因是如果while循环不是break出来的
- //会导致第一个元素值重复,插入的值最后未插入进去
- arr[end + 1] = temp;
- }
-
- }
希尔排序比插入排序多的就是预排序,而预排序的目的就是让大的数据/小的数据更快的被排到后面去,因为越接近有序的数据,使用插入排序时时间复杂度越接近O(N),而我们的希尔排序最后一步等同于插入排序
以代码一为例:

两个代码没有什么差别,只是一个是一组一组排,一个是并排。
- void ShellSort(int* arr, int n)
- {
-
- int gap = n;
-
- while (gap > 1)
- {
-
- //多组预排序,最后接近有序时插入排序
- gap /= 2;
-
- //完成一趟预排序
- for (int j = 0; j < gap; j++)
- {
- //完成一组预排序
- for (int i = j; i < n - gap; i += gap)
- {
- //走一组中的一个位置的预排序
- int end = i;
- int temp = arr[end + gap];
-
- while (end >= 0)
- {
- if (temp < arr[end])
- {
- arr[end + gap] = arr[end];
- end -= gap;
- }
- else
- {
- break;
- }
- }
-
- arr[end + gap] = temp;
- }
-
- }
- }
-
- }
- void ShellSort(int* arr, int n)
- {
- int gap = n;
-
- while (gap > 1)
- {
-
- //多组预排序,最后接近有序时插入排序
- gap /= 2;
-
- //等同于上面的希尔排序,不是分组排了,而是并排
- for (int i = 0; i < n - gap; i++)
- {
- //走一组中的一个位置的预排序
- int end = i;
- int temp = arr[end + gap];
-
- while (end >= 0)
- {
- if (temp < arr[end])
- {
- arr[end + gap] = arr[end];
- end -= gap;
- }
- else
- {
- break;
- }
- }
-
- arr[end + gap] = temp;
- }
- }
- }
