个人主页: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; } } }