首先我们先来看一下基本的七大排序,今天我们先一起学习前四个:
1、排序的概率及意义
排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起 来的操作。
稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记 录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍 在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。
内部排序:数据元素全部放在内存中的排序 。
外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据 的排序。
排序的运用:例如在淘宝购物时我们可以根据综合、销量、好评……进行排序。
2、直接插入和希尔排序的实现及分析
2.1.直接插入排序
①基本思想
直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐 个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。 实际中我们玩扑克牌时,就用了插入排序的思想:
②直接插入排序
升序:
#include<stdio.h> 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 (n > 1 && a[end] > tmp) { a[end + 1] = a[end]; --end; } else { break; } } a[end + 1] = tmp; } } void PrintArray(int* a, int n) { for (int i = 0; i < n; i++) { printf("%d ", a[i]); } printf("\n"); } void TestInsertSort() { int a[] = { 1, 3, 2, 6, 8, 7, 9, 4, 5, 0 }; int size = sizeof(a) / sizeof(int); InsertSort(a, size); PrintArray(a, size); } int main() { TestInsertSort(); return 0; }
思想: 刚开始执行时,end是数组第一个元素的下标,tmp存放的是end后面一个元素的值,让数组的end下标对应的值与tmp的值进行比较。若为升序,end下标对应的值如果大于tmp中存放的值就交换,然后让end--,然后while循环让end下标对应的值与tmp比较,若end<0就跳出,若end对应下标的值小于tmp要break(避免不必要的比较),跳出内循环后让end+1下标对应数组元素等于tmp。然后使end指向第二个元素的下标,同样的方法依次比较。
总结:
1. 元素集合越接近有序,直接插入排序算法的时间效率越高
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1),它是一种稳定的排序算法
4. 稳定性:稳定
2.2希尔排序
希尔排序可以说是直接插入排序的进阶版。
希尔排序包含两部分:预排序(接近有序)、 直接插入排序(有序)
希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有 记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重 复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。
观察以下排序:
多组间隔为gap的预排序,gap有大变小
gap越大,大的数可以越快的到很后面,小的数可以越快到前面,预排序越不接近有序
gap越小,越接近有序
gap==1时就是直接插入排序
代码:
#define _CRT_SECURE_NO_WARNINGS 1 #include //希尔排序:直接插入排序的基础上的优化 //1、先进行预排序,让数组接近有序(分组排) //2、直接插入排序 //时间复杂度为log₂N*N或者是log₃N*N void ShellSort(int* a, int n) { int gap = n; while (gap > 1) { //gap = gap / 2; //log₂N gap = gap / 3 + 1;//log₃N //gap>1时都是预排序 接近有序 //gap==1时就是直接插入排序 有序 //gap很大时,下面预排序时间复杂度O(n) //gap很小时,数组已经很接近有序了,这事差不多也是O(n) //把间隔为gap的多组数据同时排 for (int i = 0; i { int end = i; int tmp = a[end + gap]; while (end >= 0) { if (n > 1 && a[end] > tmp) { a[end + gap] = a[end]; end -= gap; } else { break; } } a[end + gap] = tmp; } } } void PrintArray(int* a, int n) { for (int i = 0; i < n; i++) { printf("%d ", a[i]); } printf("\n"); } void TestInsertSort() { int a[] = { 1, 3, 2, 6, 8, 7, 9, 4, 5, 0 }; int size = sizeof(a) / sizeof(int); ShellSort(a, size); PrintArray(a, size); } int main() { TestInsertSort(); return 0; }
希尔排序的特性总结:
① 希尔排序是对直接插入排序的优化
② 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,就是直接插入排序。它与直接插入排序的区别就是多了一个预排序,这样使时间效率更好
③ 希尔排序的时间复杂度不好计算,需要进行推导,推导出来平均时间复杂度: O(N^1.3— N^2)
④ 稳定性:不稳定