直接插入排序:
直接插入排序就是就是从end的下一位挑选一个数字不断地向前进行插入,整个过程伴随着end的位置从0置end-1,该无序数列也逐渐成为了一个有序数列!思想还是比较简单的,当原合越接近有序时,直接插入排序算法的效率越高。时间复杂度是0N的二次方,是一种比较稳定的排序方式!
当写直接插入排序的代码时,我们可以先写单次循环的代码,最后再通过在外部控制end的位置写一个大循环 !
int InsertSort(int *a, int n) { for (int i = 0; i <= n - 2; i++) { int end = i; int tmp = a[end + 1] while(end>=0){ if (a[end] > a[tmp]) { a[end + 1] = a[end]; --end; } else break; } } a[end + 1] = tmp; }
这是插入排序的代码,其中需要注意的点在于先写单次循环,而后再整体大循环,可能很多人会对a[end+a]=tmp这一句比较疑惑。其实当,end'一直减减到头会导致,end出现在-1这个位置上,tmp自然而然就会插入到end=0的位置上上。
希尔排序:
希尔排序说白了就是一种优化后的直接插入排序,不同的点在于他对数组进行了分组操作,复杂度有所减小,可以达到ON的一点三次方。希尔排序会对整个数据进行预排序->使数组接近于有序,而后会进行直接插入排序。
预排序:数组进行分组,间隔是gap的分为一组,分别进行排序,分别让着gap组数据进行插入排序。gap越小,会越接近于有序,跳的越慢。gap越大,越不接近于有序,跳的越快。当多次进行预排序,gap会变得越来越小。当gap=1时,显而易见他就是一个直接插入排序!
int ShellSort(int *a, int n) { int gap = n; while (gap>1) { gap = gap / 3 + 1; for (int i = 0; i <= n - gap; i++) { int end = i; int tmp = a[end + gap] while(end>=0){ if (a[end] > a[tmp]) { a[end + gap] = a[end]; end -= gap; } else break; } } a[end + gap] = tmp; }
这就是希尔排序的算法代码,可以看出很明显就是对直接插入排序的变形,增加了一个gap变量,用于进行分组!gap=gap/3+1这里3不能写成二,一旦写成2,会出现死循环的情况!为什么要进行+1操作呢,保证不伦n多大,最终都可以跳回到gap=1,从而进行直接插入排序!这个算法比较巧妙的地方在于,gap个间隔为gap的组进行同时交插排序!
选择排序:
一次选择两个数,最小的数放在第一个位置,最大的数放在最后的一个位置!应该去找到最小数与最大数的下标,而不是找到数,这样能防止覆盖!
void SelectSort(int *a, int n){ int begin = 0, end = n - 1; while (begin < end) {//[begin,end]中选出一个最小的,选出一个最大的下标! int mini = begin, maxi = end; for (int i = begin; i <= end; ++i) { if (a[i]>a[maxi]) maxi = i; if (a[i] < a[mini]) mini = i; } Swap(&a[begin], &a[mini]); if (begin == maxi){ maxi = mini; } Swap(&a[end], &a[maxi]); ++begin; --end; }
}
这种排序特别简单,需要注意的点就是
if (begin == maxi){ maxi = mini;
这一块,当出现情况开头第一个数字是最大的时候,会对begin与mini进行交换,但是这个时候maxi位置且没有发生变化,直接导致后一步end与maxi交换时出现,刚换过去的mini指向的最小值被交换到了数组的end端!
冒泡排序:
一次又一次的向下沉底,下面是基本代码
void BubbleSort(int *n, int n) { for (int end = n - 1; end > 0;--end){ int flag = 0; for (int i = 0, i < end; ++i) { if (a[i] > a[i + 1]){ Swap(&a[i], a[i + 1]); flag = 1; } } if (flag == 0)//说明并没有发生交换 break; } } 对于这个排序我想说的就是这个flag这一点新意,它是对冒泡排序的一种优化,当一次 内循环没有发生任何交换时(flag值恒为0)那么就可以直接跳出,这种方法对于特定的数组提高了不小的效率!