1. 程式人生 > >《演算法圖解》學習記錄------持續更新

《演算法圖解》學習記錄------持續更新

最近在學習演算法,選用的是《演算法題解》這本書,作為演算法的入門書籍。為了以後方便複習以及加強記憶,每次看完一章以後都會把知識點記錄到這個文章當中。本文的結構會參考《演算法圖解》的目錄結構,方便自己記錄。在文章中,可能會有一些LZ自己簡單實現的演算法程式碼,僅供參考。

文章中的log​​​​​​指的都是log_2,演算法速度用大O表示法來表示。

目錄

演算法:

演算法:

1、二分查詢(折半查詢)

使用場景:在一個有序的元素列表中,查詢某個資料所在的位置。

具體思想:

1.確定查詢範圍front=0,end=N-1,計算中項mid=(front+end)/2。

2.若a[mid]=x或front>=end,則結束查詢;否則,向下繼續。

3.若a[mid]<x,說明待查詢的元素值只可能在比中項元素大的範圍內,則把mid+1的值賦給front,並重新計算mid,轉去執行步驟2;若a[mid]>x,說明待查詢的元素值只可能在比中項元素小的範圍內,則把mid-1的值賦給end,並重新計算mid,轉去執行步驟2。

時間複雜度:O(log(n)

簡單程式碼實現:

    /**
     * 用二分法查詢資料在陣列中的位置,當資料存在時,返回資料所在角標,不存在時,返回-1
     *
     * @param array 被查詢的有序陣列
     * @param value 要查詢的資料
     * @return 查詢結果
     */
    public static int binary(int[] array, int value) {

        int low = 0;
        int high = array.length - 1;
        while (high >= low) {
            int mid = (low + high) / 2;
            if (array[mid] == value) {
                return mid;
            } else if (array[mid] > value) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return -1;
    }

2、選擇排序

使用場景:將一個元素列表,按照一定的要求進行排序

具體思想:

1、從待排序元素列表中找到最小(或最大)的元素,放到有序陣列中末尾。

2、對剩餘的元素重複步驟1,直到待排序的元素列表中的元素全部放到有序陣列中。

時間複雜度:O(log(n^{^{2}})

簡單程式碼實現:

    /**
     * 將一個無序int陣列從小到大排序
     *
     * @param array 要排序的int陣列
     * @return 查詢結果
     */
    public static int[] selectSort(int[] array) {

        int minIndex = 0;
        int temp = 0;
        for (int i = 0; i < array.length; i++) {
            //獲取要查詢無序陣列的第一個角標
            minIndex = i;
            for (int j = i; j < array.length; j++) {
                //找到無序陣列的最小值角標,並儲存
                if (array[minIndex] > array[j]) {
                    minIndex = j;
                }
            }
            //將要查詢陣列第一個值與最小值交換,無序陣列長度減少,前面的都是有序陣列
            temp = array[i];
            array[i] = array[minIndex];
            array[minIndex] = temp;
        }
        return array;
    }

3、快速排序

使用場景:將一個元素列表,按照一定的要求進行排序

具體思想:

1、選擇基準值。

2、將元素列表分為兩個子列表:小於基準值和大於基準值。

3、對這兩個子陣列再次進行步驟1-2操作

時間複雜度:O(log(n log n)

簡單程式碼實現:

/**
     * 對陣列進行從小到大排序
     *
     * @param array 要排序的陣列
     * @param low   要從陣列哪一位開始排序
     * @param high  排序位置要截止到陣列的哪一位
     */
    public static void quickSort(int[] array, int low, int high) {

        //判斷陣列是否需要排序
        if (low < high) {
            //將元素列表分為兩個子列表:小於基準值和大於基準值,並返回基準值所在的位置
            int middle = getMid(array, low, high);
            //對小於基準值的陣列再次排序
            quickSort(array, low, middle - 1);
            //對大於基準值的陣列再次排序
            quickSort(array, middle + 1, high);
        }
    }

    /**
     * 將陣列按照基準值分為大於基準值和小於基準值兩部分,並返回基準值所在的座標
     *
     * @param array 要排序的陣列
     * @param low   要從陣列哪一位開始排序
     * @param high  排序位置要截止到陣列的哪一位
     * @return 基準值所在的角標
     */
    public static int getMid(int[] array, int low, int high) {
        //陣列的第一個作為基準值
        int tmp = array[low];
        //對陣列中的值進行遍歷
        while (low < high) {
            //從右往左找比基準值小的數
            while (low < high && array[high] >= tmp) {
                high--;
            }
            //將找到的比基準值小的數插在左端
            array[low] = array[high];
            //從左往右找比基準值大的數
            while (low < high && array[low] < tmp) {
                low++;
            }
            //將找到的比基準值大的數插在右端
            array[high] = array[low];
        }
        //將基準值插到已經分好大小的陣列中間
        array[low] = tmp;
        //返回基準值目前所在的位置
        return low;
    }

4、廣度優先搜尋 

使用場景:解決路徑最短問題。(1)從節點A出發,又到達節點B的路徑嗎?(2)從節點A出發,到達節點B的哪條路徑最短?

具體思想:從圖中某頂點v出發,在訪問了v之後依次訪問v的各個未曾訪問過的鄰接點,然後分別從這些鄰接點出發依次訪問它們的鄰接點,並使得“先被訪問的頂點的鄰接點先於後被訪問的頂點的鄰接點被訪問,直至圖中所有已被訪問的頂點的鄰接點都被訪問到。如果此時圖中尚有頂點未被訪問,則需要另選一個未曾被訪問過的頂點作為新的起始點,重複上述過程,直至圖中所有頂點都被訪問到為止。

文章相關知識點

這裡是《演算法圖解》中提到的額外的知識點,有助於瞭解和學習演算法:

1、大O表示法含義

2、D&C(分而治之)原理

3、遞迴原理

4、記憶體工作原理

5、陣列和連結串列結構

6、呼叫棧過程

7、散列表原理

8、歐幾里得定律

9、佇列和棧結構