一些辅助函数。

  1. /**
  2. * 辅助函数:用于交换两个值
  3. *
  4. * @param array
  5. * @param a
  6. * @param b
  7. */
  8. public static void exchange(int[] array, int a, int b) {
  9. int tmp = array[a];
  10. array[a] = array[b];
  11. array[b] = tmp;
  12. }
  13. /**
  14. * 辅助函数:用于比较大小
  15. *
  16. * @param valueA
  17. * @param valueB
  18. * @return
  19. */
  20. public static Boolean less(int valueA, int valueB) {
  21. return valueA < valueB;
  22. }

选择排序

基本思路:首先,找到数组中最小的那个元素,其次,将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。再次,在剩下的元素中找到最小的元素,将它与数组中的第二个元素交换位置。如此往复,直到将整个数组排序。

  1. /**
  2. * 选择排序算法
  3. *
  4. * @param array
  5. * @return
  6. */
  7. public static int[] selection(int[] array) {
  8. for (int i = 0; i < array.length; i++) {
  9. int min = i;
  10. for (int j = i + 1; j < array.length; j++) {
  11. if (less(array[j], array[min])) min = j;
  12. }
  13. exchange(array, i, min);
  14. }
  15. return array;
  16. }

比较次数和交换次数

第一轮循环比较 选择、插入、希尔排序 - 图1 次、第二轮循环比较 选择、插入、希尔排序 - 图2 次、第三轮循环比较 选择、插入、希尔排序 - 图3 次 … 第 选择、插入、希尔排序 - 图4 轮循环比较 选择、插入、希尔排序 - 图5 次。

所以是一个以 选择、插入、希尔排序 - 图6选择、插入、希尔排序 - 图7,公差为 选择、插入、希尔排序 - 图8,一共 选择、插入、希尔排序 - 图9 项的等差数列。

求和为选择、插入、希尔排序 - 图10

从代码中可以知道一共交换次数为 N 次。

插入排序

基本思路:通过构建有序序列,对于未排序的数据,在已排序序列中从后往前扫描,找到相应的位置插入并插入。需要反复地把已排序元素逐步向后挪位,为最新的元素提供插入空间。

  1. /**
  2. * 插入排序算法
  3. * @param array
  4. * @return
  5. */
  6. public static int[] Insertion(int[] array) {
  7. for (int i = 1; i < array.length; i++) {
  8. for (int j = i; j > 0 && less(array[j], array[j - 1]); j--) {
  9. exchange(array, j, j - 1);
  10. }
  11. }
  12. return array;
  13. }

比较的次数和交换次数

最坏情况

数列是一个降序数组。

第一轮循环比较 选择、插入、希尔排序 - 图11 次、第二轮循环比较 选择、插入、希尔排序 - 图12 次、第三轮循环比较 选择、插入、希尔排序 - 图13 次 … 第 选择、插入、希尔排序 - 图14 轮循环比较 选择、插入、希尔排序 - 图15 次。

所以是一个以 选择、插入、希尔排序 - 图16选择、插入、希尔排序 - 图17,公差为 选择、插入、希尔排序 - 图18,一共 选择、插入、希尔排序 - 图19 项的等差数列。

求和为选择、插入、希尔排序 - 图20

因为每次比较都需要交换,所有交换次数也是 选择、插入、希尔排序 - 图21

最好情况

数组是一个升序数组。

交换次数为 选择、插入、希尔排序 - 图22 次,比较次数为 选择、插入、希尔排序 - 图23(因为每轮循环都只会比较一次)。

平均情况

把最好的情况和最差情况求和平均。

平均比较次数 选择、插入、希尔排序 - 图24
平均交换次数 选择、插入、希尔排序 - 图25

希尔排序

基本思路:将待排序的数组元素按小标的一定增量分组,分成多个子序列,然后对各个子序列进行直接的排序算法排序;然后依次缩减增量再进行排序,直到增量为 1 时,进行最后一次直接插入排序,排序结束。

讲解视频 ShellSort.mp4

  1. /**
  2. * 希尔排序算法
  3. * @param array
  4. * @return
  5. */
  6. public static int[] ShellSort(int[] array) {
  7. int N = array.length;
  8. int h = 1;
  9. if(h < N / 3) h = h * 3 + 1;
  10. while (h >= 1){
  11. for(int i = h; i < N; i++) {
  12. for(int j = i; j >= h && less(array[j], array[j-h]); j -= h) {
  13. exchange(array, j, j - h);
  14. }
  15. }
  16. h = h / 3;
  17. }
  18. return array;
  19. }

交换次数和比较次数不会算。。。。

参考: