算法(第四版)之选择排序和插入排序

排序在我们的生活和生产中是很重要的, 据说在计算时代早期, 大家普遍认为30%的计算周期都用在了排序上, 现在的这个比例下降了, 原因可能是排序算法更加高效, 但绝不可能是因为排序的重要性降低了

这篇文章不会像书上说的那样实现Comparable接口, 接下来的所有代码都将是对整型数组的操作

选择排序的思路很简单, 就是遍历整个数组, 将最小的数挑出来, 放在第一个的位置上, 之后继续遍历, 循环N次, 这里用到了双重循环, 所以我们可以很轻松的了解到它的时间复杂度为O(n):

 1 public class SelectSort {
 2    public static void main(String[] args) {
 3         int a[] = new int[]{2, 4, 1, 5, 6, 8, 0, 7, 3, 9};
 4         for(int i = 0; i < 10; i++)
 5             System.out.print(a[i] + " ");
 6         System.out.println();
 7         
 8         for(int i = 0; i < 10; i++) {
 9             int min = i;
10             for(int j = i + 1; j < 10; j++) {
11                 if(a[j] < a[min]) {
12                     min = j;
13                 }
14             }
15             int tmp = a[i];
16             a[i] = a[min];
17             a[min] = tmp;
18         }
19         
20         for(int i = 0; i < 10; i++)
21             System.out.print(a[i] + " ");
22         System.out.println();
23     } 
24 
25 }

插入排序的思路就是对于这个数组, 有两个部分, 已排好序的部分和未排好序的部分, 我们每次都将未排好序的部分的第一个数插入到已排好序的部分的相应位置, 然后已排好序的部分加一, 未排好序的部分减一, 直到数组全部排好序. 在这其中, 我们也用到了双重循环, 所以我们也可以很轻易的得到它的时间复杂度也是O(n):

 1 public class InsertionSort{
 2     public static void main(String[] args) {
 3         int a[] = new int[]{-1, 2, 4, 1, 5, 6, 8, 0, 7, 3, 9};
 4         for(int i = 1; i < 11; i++)
 5             System.out.print(a[i] + " ");
 6         System.out.println();
 7 
 8         for(int i = 1; i < 10; i++) {
 9             for(int j = i; a[j] < a[j-1] && j < 10; j--) {
10                 if(j <= 0)
11                     break;
12                 int tmp = a[j];
13                 a[j] = a[j-1];
14                 a[j-1] = tmp;
15             }
16         }
17 
18         for(int i = 1; i < 11; i++)
19             System.out.print(a[i] + " ");
20         System.out.println();
21     }
22 }

我们也将a[0]设置为哨兵, 我们将哨兵作为边界, 它的作用就是当循环到了边界时会停下来, 这样我们就不用每次都询问是否到达了边界:

 1 public class InsertionSort{
 2     public static void main(String[] args) {
 3         int a[] = new int[]{-1, 2, 4, 1, 5, 6, 8, 0, 7, 3, 9};
 4         for(int i = 1; i < 11; i++)
 5             System.out.print(a[i] + " ");
 6         System.out.println();
 7 
 8         for(int i = 2; i < 10; i++) {
 9             a[0] = a[i];
10             int j = i;
11             for(; a[j] < a[j-1]; j--) {
12                 a[j] = a[j-1];
13             }
14             a[j-1] = a[0];
15         }
16 
17         for(int i = 1; i < 11; i++)
18             System.out.print(a[i] + " ");
19         System.out.println();
20     }
21 }

虽然二者的时间复杂度都是O(n), 但相较于选择排序, 插入排序有一个特点, 那就是它可以在数据传输过程中它就可以进行排序, 而选择排序不行, 打个比方, 你在打扑克牌时, 如果是选择排序, 你只能在摸玩所有的牌之后进行排序, 但是如果是插入排序, 你可以在摸牌的过程中就将手上已经有的牌排好序, 让你手中已经有的牌一直保持有序状态

虽然这两种排序都很简单, 效率也不是很高, 但是他们有一些其他的高级算法所不具有的特性, 也可以对其他的较为高级的排序进行优化, 让那些高级的排序算法更加高效

猜你喜欢

转载自www.cnblogs.com/qq1914808114/p/10808605.html