这次来聊聊几个简单的排序算法:插入排序、希尔排序、选择排序、冒泡排序与地精排序。由于我本身不是很想深究这方面的内容,只是应付一下课业,所以就简单介绍一下。反正用处也不是特别大……
插入排序
1 2 3 4 5 6 7 8 9 10 11
| template <class Type> void InsertSort(Type arr[], int n) { int i, j; for (i = 1; i < n; i++) { Type temp = arr[i]; for (j = i - 1; j >= 0 && arr[j] > temp; j--) arr[j + 1] = arr[j]; arr[j + 1] = temp; } }
|
对于插入排序,最好的情况是所有数据在表中已为升序排列,此时只需要进行 n-1 次比较, 0 次移动。而最差的情况即为数据在表中为降序排列。
在 清华大学版数据结构教材 中,数组的第 [0] 位起到 哨兵 作用,所以算法的代码实现与操作数分析可能与以上结果有 细微差别 。
希尔排序
希尔排序的实现过程与插入排序类似,或者说,就是加强版的插入排序。其基本思路是 将整个数据表分成m个子序列,对每个子序列分别进行插入排序 ,并逐步减少子序列数m,直到m=1为止。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| template <class Type> void ShellSort(Type arr[], int n) { int deltas[] = {5, 3, 1}; for (int i = 0; i < 3; i++) ShellInsert(arr, n, deltas[i]); } template <class Type> void ShellInsert(Type arr[], int n, int delta) { Type temp; int i, j; for (i = delta; i < n; i++) { temp = arr[i]; for (j = i - delta; (j >= i % delta) && arr[j] > temp; j -= delta) arr[j + delta] = arr[j]; arr[j + delta] = temp; } }
|
举个例子:
希尔排序的效率与希尔增量 deltas[]
的取值有关,一般情况下有几种典型求法,可以自行了解,这边不多赘述。
选择排序
顾名思义,选择排序便是每次从 当前位置之后 的数据中选择一个最小值,将其置于当前位置,最终使得序列升序排列:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| template <class Type> void SelectSort(Type arr[], int n) { for (int i = 0; i < n; i++) { int min_index = i; for (int j = i + 1; j < n; j++) if (arr[j] < arr[min_index]) min_index = j; swap(arr[i], arr[min_index]); } } template <class Type> void swap(Type& a, Type& b) { Type temp = a; a = b; b = temp; }
|
冒泡排序
不会有人学到这里还不会冒泡排序吧?
1 2 3 4 5 6 7
| template <class Type> void BubbleSort(Type arr[], int n) { for (int i = 0; i < n - 1; i++) for (int j = 0; j < n - i - 1; j++) if (arr[j] > arr[j + 1]) swap(arr[j], arr[j + 1]); }
|
地精排序
1 2 3 4 5 6 7 8 9 10 11 12 13
| template <class Type> void GnomeSort(Type arr[], int n) { int i = 0; while (i < n) { if (i == 0 || arr[i - 1] <= arr[i]) i++; else { swap(arr[i - 1], arr[i]); i--; } } }
|
地精排序,看起来只用了一重循环,可实际上还是和冒泡排序一样的原理,一样的低效……