注:稳定排序算法会让原本有相等键值的纪录维持相对顺序。也就是说:如果一个排序算法是稳定的,当有两个相等键值的纪录R和S,且在原本的列表中R出现在S之前,在排序过的列表中R也将会是在S之前。

1.冒泡排序

冒泡排序是针对数组的排序算法,其最优时间复杂度为O(n),即数组本来就有序;最差时间复杂度为O(n^2),即数组完全按照相反次序排列;平均时间复杂度为O(n^2)。其最差空间复杂度为O(n),额外空间O(1)。

Java实现代码:

package com.xyy.interview;
public class BubbleSort {
    public static void main(String[] args) {
        int[] number = {95, 45, 15, 78, 84, 51, 24, 12};
        bubble_sort(number);
        for (int i = 0; i < number.length; i++) {
            System.out.print(number[i] + " ");
        }
    }
    
    public static void bubble_sort(int[] arr) {
        int temp, len = arr.length;
        for(int i = 0; i < len - 1; i++) {
            for (int j = 0; j < len - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}

2.选择排序

选择排序是针对数组的排序,排序后原来的数组的相对次序可能发生变化,故选择排序是不稳定的排序算法。选择排序主要进行两部分操作:比较数组中键值的大小和对符合条件的键值对进行移动。

当i=1时,需要进行n-1次比较;当i=2时,需要进行n-2次比较;n=3时,需要进行n-3次比较...根据递推规律,得到总共需要比较的次数为:(n-1)+(n-2)+...+3+2+1=n(n-1)/2。移动次数是在n个数之间进行,不可能把已经移动的两个数再次移动到原来的位置,故选择排序的比较的时间复杂度为O(n^2),移动的时间复杂度为O(n),需要额外的空间进行。

Java代码:

package com.xyy.interview;

public class SimpleSort {

    public static void main(String[] args) {
        int[] number = { 3, 1, 2, 8, 4, 5, 24, 12 };
        simple_sort(number);
        for (int i = 0; i < number.length; i++) {
            System.out.print(number[i] + " ");
        }
    }

    public static void simple_sort(int[] arr) {
        int length = arr.length;
        int temp;
        for (int i = 0; i < length - 1; i++) {
            int min = i;
            for (int j = i + 1; j < length; j++) { // 寻找最小的数
                if (arr[j] < arr[min]) {
                    min = j;
                }
            }
            if (min != i) {
                temp = arr[min];
                arr[min] = arr[i];
                arr[i] = temp;
            }
        }
    }
}

3.快速排序

快速排序是对冒泡排序的一种改进。快速排序是使用分治法进行排序的一种比较的实例,它把一个序列(或者说是数组)分成两个子序列,再对这两个子序列进行排序,最后将排序后的两个子序列进行合并即可得到最后有序的序列。

快速排序是针对数组的排序。通常情况下,快速排序需要对n个数进行O(n*logn)次比较(平均情况);在最坏的情况下(即选择分支的时候选择数不妥或者说原来数组的排列是反向的)需要进行O(n^2)次比较。故快速排序的平均时间复杂度为O(n*logn),最差时间复杂度为O(n^2)。

Java实现代码

package com.xyy.interview;

public class QuickSort {

    public static void main(String[] args) {
        int[] arr = { 8, 1, 0, 4, 6, 2, 7, 9, 5, 3 };
        quickSort(arr, 0, arr.length - 1);
        for (int i : arr) {
            System.out.print(i + " ");
        }
    }

    public static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            int middle = getMiddle(arr, low, high);
            quickSort(arr, low, middle - 1);
            quickSort(arr, middle + 1, high);
        }
    }

    public static int getMiddle(int[] list, int low, int high) {
        int tmp = list[low];
        while (low < high) {
            while (low < high && list[high] >= tmp) {
                high--;
            }
            list[low] = list[high];
            while (low < high && list[low] <= tmp) {
                low++;
            }
            list[high] = list[low];
        }
        list[low] = tmp;
        return low;
    }
}