算法學(xué)習(xí)筆記 - Alogrithm Fourth Edition

算法學(xué)習(xí)筆記 - Alogrithm Fourth Edition

排序算法

選擇排序(Selection)

如果有N個(gè)數(shù)組,從第一個(gè)元素開始往后選擇,與后面的每一個(gè)元素做對(duì)比,挑出最小的元素,如果后面元素中有一個(gè)最小的值,則把這個(gè)值放到第一位。然后從第二位數(shù)開始,繼續(xù)往后面的元素做對(duì)比,挑出最小元素,如果后面元素中有一個(gè)最小的值,則把這個(gè)值放到第二位。以此重復(fù)操作到第N位,排序就完成了。

public class Selection {
    Selection() {

    }

    public static void main(String[] args) {
        int[] a = new int[] { 1, 2, 5, 7, 9, 12, 93, 5, 4, 6, 88 };
        show(a);
        Selection.sort(a);
        show(a);
    }

    public static void sort(int[] a) {
        for (int i = 0; i < a.length; i++) {
            int mini = i;
            for (int j = i + 1; j < a.length; j++) {
                if (less(a[j], a[mini])) {
                    mini = j;
                }
            }
            exch(a, i, mini);
        }
    }

    private static boolean less(int v, int w) {
        return v < w;
    }

    private static void exch(int[] a, int i, int j) {
        Object swap = a[i];
        a[i] = a[j];
        a[j] = (int) swap;
    }

    private static void show(int[] a) {
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i] + " ");
        }
        System.out.println();
    }
}

插入排序

假設(shè)有N個(gè)元素的數(shù)組,從第二元素開始,與左邊的第一元素比較,如果第二個(gè)比第一個(gè)元素小則插入第一個(gè)前面。接著從第三個(gè)開始與左邊元素與第二個(gè)比較,如果第三個(gè)小于第二個(gè),則插入到第二個(gè)前面,接著比較第一個(gè)。以此類推。

package com.srs.test;

public class Insert {
    Insert() {
    }

    public static void main(String[] args) {
        int[] a = new int[] { 1, 2, 5, 7, 9, 12, 93, 5, 4, 6, 88 };
        show(a);
        Selection.sort(a);
        show(a);
    }

    private void sort(int[] a) {
        for (int i = 1; i < a.length; i++) {
            for(int j = i;j>0&&less(a,j,j-1);j--){
                exch(a,j,j-1);
            }
        }
    }
    
    private boolean less(int[] a,int i,int j){
        return a[i]<a[j];
    }
    
    private static void exch(int[] a, int i, int j) {
        Object swap = a[i];
        a[i] = a[j];
        a[j] = (int) swap;
    }
    
    private static void show(int[] a) {
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i] + " ");
        }
        System.out.println();
    }
}

希爾排序

插入排序在極端情況下有可能最右端的數(shù)值要經(jīng)過其他全部數(shù)值的比較才到達(dá)第一位。所以當(dāng)數(shù)組長(zhǎng)度很大時(shí),排序的效率就非常低了,后來便有了希爾排序,希爾排序是插入排序的優(yōu)化,它的基礎(chǔ)原理思想就是,將數(shù)組分成幾個(gè)小隊(duì)列,讓數(shù)組元素跨數(shù)組排列。當(dāng)分組排列完成后,縮小組別的長(zhǎng)度,重復(fù)上面的排序,直至最后做普通的插入排序即完成了希爾排序;

  • 例如,假設(shè)有這樣一組數(shù)[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我們以步長(zhǎng)為5開始進(jìn)行排序,我們可以通過將這列表放在有5列的表中來更好地描述算法,這樣他們就應(yīng)該看起來是這樣:

13 14 94 33 82
25 59 94 65 23
45 27 73 25 39
10

然后我們對(duì)每列進(jìn)行排序:

10 14 73 25 23
13 27 94 33 39
25 59 94 65 82
45

將上述四行數(shù)字,依序接在一起時(shí)我們得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ].這時(shí)10已經(jīng)移至正確位置了,然后再以3為步長(zhǎng)進(jìn)行排序:

10 14 73
25 23 13
27 94 33
39 25 59
94 65 82
45

排序之后變?yōu)椋?/p>

10 14 13
25 23 33
27 25 59
39 65 73
45 94 82
94

最后以1步長(zhǎng)進(jìn)行排序(此時(shí)就是簡(jiǎn)單的插入排序了)。

代碼如下:

public class Shell extends BaseClass {
    public static void main(String[] args) {
        startTest(new Shell());
    }

    @Override
    public void sort(int[] a) {
        int n = a.length;
        int h = 1;
        while (h < n / 3)
            h = 3 * h + 1;
        while (h >= 1) {
            for (int i = h; i < n; i++) {
                for (int j = i - h; j >= 0 && less(a, j + h, j); j -= h) {
                    exch(a, j + h, j);
                }
            }
            h /= 3;
        }
    }
}

歸并排序

分治是歸并排序的基本思想,將一數(shù)組通過不斷的分化,直至最小,元素?cái)?shù)量為2的小數(shù)組,小數(shù)組排序后再和其他小數(shù)組合并合并的時(shí)候也做排序,合并完成后再與另外一組同樣有小數(shù)組再繼續(xù)合并,指導(dǎo)最終排序完成

public class Merge extends BaseClass {
    public static void main(String[] args) {
        startTest(new Merge());
    }

    @Override
    public void sort(int[] a) {
        sort(a,0,a.length-1);
    }

    public void sort(int[] a, int lo, int hi) {
        if (hi <= lo)
            return;
        int mid = lo+(hi - lo) / 2;
        sort(a, lo, mid);
        sort(a, mid + 1, hi);
        merge(a, lo, mid, hi);
    }

    public void merge(int[] a, int lo, int mid, int hi) {
        int i = lo, j = mid + 1;
        int[] arr = new int[a.length];
        for (int k = lo; k <= hi; k++) {
            arr[k] = a[k];
        }
        for (int k = lo; k <= hi; k++) {
            if (i > mid) {
                a[k] = arr[j++];
            } else if (j > hi) {
                a[k] = arr[i++];
            } else if (less(arr[j], arr[i])) {
                a[k] = arr[j++];
            } else {
                a[k] = arr[i++];
            }
        }

    }

}

快速排序

快速排序使用分治法(Divide and conquer)策略來把一個(gè)序列(list)分為兩個(gè)子序列(sub-lists)。選取一個(gè)基準(zhǔn)值,程序同時(shí)從左端和右端向中間靠攏,首先左端和右端同基準(zhǔn)值做比較,左端小于基準(zhǔn)值時(shí)光標(biāo)繼續(xù)移動(dòng),直至左端大于基準(zhǔn)值,右端的大于基準(zhǔn)值時(shí)光標(biāo)繼續(xù)移動(dòng),直至右端小于基準(zhǔn)值,這時(shí)候交換左端右端位置。接著繼續(xù)移動(dòng)左右端光標(biāo)重復(fù)以上操作。當(dāng)兩端相遇時(shí)完成左右端大小歸類。然后繼續(xù)分裂左右端歸類后的數(shù)組,數(shù)組不能再繼續(xù)分裂排序就完成了

public class Quick extends BaseClass {
    public static void main(String[] args) {
        startTest(new Quick());
    }
    
    @Override
    public void sort(int[] a) {
        sort(a,0,a.length-1);
    }

    public void sort(int[] a, int lo, int hi) {
        if (lo >= hi) {
            return;
        }
        int j = partition(a, lo, hi);
        sort(a, lo, j-1);
        sort(a, j + 1, hi);
    }

    private int partition(int[] a, int lo, int hi) {
        int i = lo, j = hi + 1;
        int v = a[lo];
        while (true) {

            while (less(a[++i], v)) {
                if (i == hi) {
                    break;
                }
            }

            while (less(v, a[--j])) {
                if (j == lo) {
                    break;
                }
            }

            if (i >= j) {
                break;
            }

            exch(a, i, j);
        }
        exch(a, lo, j);
        return j;
    }
}

優(yōu)先隊(duì)列

堆的定義

當(dāng)一棵二叉樹的每一個(gè)結(jié)點(diǎn)都大于等于它的兩個(gè)子節(jié)點(diǎn)是,它被稱為有序堆

最后編輯于
?著作權(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)容