簡(jiǎn)單排序

排序是基礎(chǔ)的算法問題,常見的排序有插入排序、冒泡排序、快速排序等,它們分別有不同的計(jì)算復(fù)雜度。插入排序和冒泡排序的復(fù)雜度為O(n^2),而快速排序的復(fù)雜度為O(nlogn)。因此,快速排序是最常用的排序方法之一,因?yàn)樗膹?fù)雜度更。然而,對(duì)簡(jiǎn)單的排序方法的理解,還是有必要的。

插入排序 (Insert Sort)

插入排序的原理是將亂序的數(shù)據(jù)依次插入有序的數(shù)組中,其中每個(gè)數(shù)據(jù)的插入,都需要遍歷一次已排好序的數(shù)組,因此會(huì)用到兩層循環(huán)嵌套,復(fù)雜度為O(n^2)

InsertSort (from Wikepedia)

插入排序?qū)崿F(xiàn)方法

public class InsertSort {
    public static int[] isort(int[] num) {
        for (int i = 1; i < num.length; i++) {
            int tmp = num[i];
            int j;
            for (j = i - 1; j >= 0 && tmp < num[j]; j--) {
                num[j+1] = num[j];
            }
            num[j+1] = tmp;
        }
        return num;
    }
}

冒泡排序 (Bubble Sort)

冒泡排序的原理是把亂序數(shù)據(jù)的最大值(或最小值)依次排到數(shù)組邊緣,其中每個(gè)最大值(或最小值)的排出,都要遍歷一次未排好序的數(shù)組,因此也會(huì)用到兩層循環(huán)嵌套,復(fù)雜度為O(n^2)

BubbleSort (from Wikepedia)

冒泡排序?qū)崿F(xiàn)方法

public class BubbleSort {
    public static ArrayList<Integer> bsort(ArrayList<Integer> num) {
        for (int i = 0; i < num.size() - 1; i++) {
            for (int j = num.size() - 1; j > i; j--) {
                if (num.get(j) < num.get(j-1)) {
                    int tmp = num.get(j);
                    num.set(j, num.get(j-1));
                    num.set(j-1, tmp);
                }
            }
        }
        return num;
    }
}

快速排序 (Quick Sort)

快速排序是目前最常用的排序方法之一,因其計(jì)算效率高,復(fù)雜度只有O(nlogn)。它采用了很多巧妙的方法,例如雙指針、遞歸等,其原位排序的特性又極大節(jié)省了運(yùn)算所需的內(nèi)存空間

快速排序?qū)崿F(xiàn)方法

public class Sorter {

    public static void qsort(Integer head, Integer tail, ArrayList<Integer> input) {
        if (head >= tail || input.isEmpty() || input.size() <= 1) {
            return;
        }
        int i = head;
        int j = tail;
        
        // 1.任意取一個(gè)數(shù),這里取數(shù)組中位數(shù)下標(biāo)的對(duì)應(yīng)值
        Integer pivot = input.get((i + j) / 2);
        System.out.print("before qsort:");
        for (int k = head; k <= tail; k++) {
            System.out.print(input.get(k)+" ");
        }
        System.out.print("\n");
        
        // 2.排序,將小于pivot的值放在左邊,大于pivot的值放在右邊
        while (i <= j) {
            while (input.get(i) < pivot) {
                // 無需變換位置,光標(biāo)移到后一個(gè)位置
                i++;
            }
            
            while (input.get(j) > pivot) {
                // 無需變換位置,光標(biāo)移到前一個(gè)位置
                j--;
            }
            
            if (i < j) {
                // 數(shù)據(jù)交換,然后繼續(xù)移動(dòng)光標(biāo)
                Integer tmp = input.get(i);
                input.set(i, input.get(j));
                input.set(j, tmp);
                i++;
                j--;
            }
            
            // 必須用else if而不能用if,交換后重新進(jìn)入循環(huán),否則可能會(huì)出現(xiàn)剩下的值卡在中間無法排序的現(xiàn)象
            else if (i == j) {
                System.out.println("i == j");
                i++;                                 // 剩下一個(gè)恰好等于pivot的數(shù)
            }
        }
        
        // 3.分塊,繼續(xù)排序
        System.out.print("after qsort:");
        for (int k = head; k <= tail; k++) {
            System.out.print(input.get(k)+" ");
        }
        System.out.print("\n\n");

        // 遞歸繼續(xù)排序
        qsort(head, j, input);
        qsort(i, tail, input);
    }
}

測(cè)試

import java.util.ArrayList;

public class Main {

    public static void main(String[] args) {

        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(9);
        list.add(7);
        list.add(8);
        list.add(5);
        list.add(7);
        list.add(10);
        list.add(2);
        list.add(4);
        list.add(3);
        list.add(1);
        Sorter.qsort(0, list.size()-1, list);
        System.out.print(list);
    }
}

結(jié)果

before qsort:9 7 8 5 7 10 2 4 3 1 
after qsort:1 3 4 5 2 10 7 8 7 9 

before qsort:1 3 4 5 2 
after qsort:1 3 2 5 4 

before qsort:1 3 2 
after qsort:1 2 3 

before qsort:1 2 
i == j
after qsort:1 2 

before qsort:5 4 
after qsort:4 5 

before qsort:10 7 8 7 9 
i == j
after qsort:7 7 8 10 9 

before qsort:7 7 8 
after qsort:7 7 8 

before qsort:7 8 
i == j
after qsort:7 8 

before qsort:10 9 
after qsort:9 10 

[1, 2, 3, 4, 5, 7, 7, 8, 9, 10]

過程分析

主要體現(xiàn)的是分而治之的思想,用兩個(gè)指針來記錄位置,每一次迭代,都將數(shù)組分成兩塊,將小于等于所取值的數(shù)據(jù)放于左邊,大于所取值的數(shù)據(jù)放于右邊,以棧的形式記錄當(dāng)前狀態(tài),再次遞歸排序。

上例求解的具體先后順序如圖所示:

求解順序

維基上對(duì)快速排序的過程也有詳細(xì)的圖示:

QuickSort (from Wikipedia)

Gif中表達(dá)的就是快速排序法,它取數(shù)組最后一個(gè)數(shù)據(jù)作為比較值,然后再交換到中間,大體思路是相同的

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容