排序算法

排序算法


冒泡排序

分析
比较从0arr.length每一对数字,如果前一个数字大于(或小于)后一个数字,则交换位置,这样外层for循环每执行一次就把数组中的最大(小)数,移动到数组的最后。所以在内层for循环中可以不用比较已经排好序的数字,即arr.length-i之后的数字。时间复杂度为O(n^2)

代码

  • 伪代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function bubble_sort (array, length) {
    var i, j;
    for(i from 0 to length-1){
    for(j from 0 to length-1-i){
    if (array[j] > array[j+1])
    swap(array[j], array[j+1])
    }
    }
    }
  • Java代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public class 冒泡排序 {
    public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int n = in.nextInt();
    int[] arr = new int[n];
    for(int i = 0; i < arr.length; i++){
    arr[i] = in.nextInt();
    }

    for(int i = 0; i < arr.length-1; i++){
    for(int j = 0; j < arr.length-1-i; j++){
    if(arr[j]>arr[j+1]){
    int temp = arr[j+1];
    arr[j+1] = arr[j];
    arr[j] = temp;
    }
    }
    for(int j = 0; j < arr.length; j++){
    System.out.print(arr[j]+" ");
    }
    System.out.println("");
    }
    }
    }

打印结果
输入

1
2
10
8 100 50 22 15 6 1 1000 999 0

输出

1
2
3
4
5
6
7
8
9
8 50 22 15 6 1 100 999 0 1000 
8 22 15 6 1 50 100 0 999 1000
8 15 6 1 22 50 0 100 999 1000
8 6 1 15 22 0 50 100 999 1000
6 1 8 15 0 22 50 100 999 1000
1 6 8 0 15 22 50 100 999 1000
1 6 0 8 15 22 50 100 999 1000
1 0 6 8 15 22 50 100 999 1000
0 1 6 8 15 22 50 100 999 1000

直接插入排序

分析
有一个数组[89, 27, 35, 78, 41, 15],分为已经排好序的部分[89]和未进行排序的部分[27, 35, 78, 41, 15]
然后取出27,与排好序的部分从后往前比较,找到适合27的位置0
把排好序的数组的位置0之后的部分数组往后移一位,将27填入位置0中,完成一次插入排序。
其他依次类推

代码

  • 伪代码

    1
    2
    3
    4
    5
    6
    7
    8
    function bubble_sort (array, length) {
    var i, j;
    for(i from 0 to length-1){
    for(j from length-1 to 0)
    if(array[j] <= array[j+1]) break;
    swap(array[j], array[j+1]);
    }
    }
  • Java代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public class 插入排序 {
    public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int n = in.nextInt();
    int[] arr = new int[n];
    for(int i = 0; i < arr.length; i++){
    arr[i] = in.nextInt();
    }
    for(int i = 1; i < arr.length; i++){
    for(int j = i-1; j>=0 && arr[j]>arr[j+1]; j--){
    int temp = arr[j];
    arr[j] = arr[j+1];
    arr[j+1] = temp;
    }
    for(int i = 0; i < arr.length; i++){
    System.out.print(arr[i]+" ");
    }
    System.out.println("");}
    }
    }
    }

打印结果
输入

1
2
6
89 27 35 78 41 15

输出

1
2
3
4
5
27 89 35 78 41 15 
27 35 89 78 41 15
27 35 78 89 41 15
27 35 41 78 89 15
15 27 35 41 78 89

快速排序

分析
从小到大排序,标记最左边的数为key,然后从往左找比key小的数,再从往右找比key大的数,交换位置,最后左右扫描到同一个位置时结束,二分,
对左子数组和右子数组进行下一轮排序。

代码

  • 伪代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function quick_sort (array, left, right) {
    var l = left;
    var r = right;
    var key = array[left];
    while(l<r){
    while(l<r && array[r]>=key) r--;//必须先从右开始
    while(l<r && array[l]<=key) l++;
    if(l<r) swap(arr[l], arr[r]);
    }
    array[left] = array[l];//交换终点值和key的位置
    array[l] = key;
    quick_sort(arr, l+1, right);//二分排序,顺序不重要
    quick_sort(arr, left, l-1);
    }
  • Java代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    public class Main{
    public static void main(String[] args) throws Exception {
    Scanner in = new Scanner(System.in);
    int n = in.nextInt();
    int[] arr = new int[n];
    for(int i = 0; i < arr.length; i++){
    arr[i] = in.nextInt();
    }
    quickSort(arr, 0, arr.length-1);
    printf(arr);
    }
    private static void quickSort(int[] arr, int left, int right) {
    if(left>right) return;
    int l = left;
    int r = right;
    int key = arr[left];
    while(l<r){
    while(l<r && arr[r]>=key) r--;
    while(l<r && arr[l]<=key) l++;
    if(l<r){
    int temp = arr[l];
    arr[l] = arr[r];
    arr[r] = temp;
    }
    printf(arr);
    }
    arr[left] = arr[l];
    arr[l] = key;
    quickSort(arr, l+1, right);
    quickSort(arr, left, l-1);
    }
    private static void printf(int[] arr){
    for(int i = 0; i < arr.length; i++){
    System.out.print(arr[i]+" ");
    }
    System.out.println("");
    }
    }

打印结果
输入

1
2
10
6 1 2 7 9 3 4 5 10 8

输出

1
2
3
4
5
6
7
8
9
10
6 1 2 5 9 3 4 7 10 8 
6 1 2 5 4 3 9 7 10 8
6 1 2 5 4 3 9 7 10 8
3 1 2 5 4 6 9 7 8 10
3 1 2 5 4 6 9 7 8 10
3 1 2 5 4 6 8 7 9 10
3 1 2 5 4 6 7 8 9 10
2 1 3 5 4 6 7 8 9 10
2 1 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10

参考资料:

白话经典算法系列之二 直接插入排序的三种实现