1. 程式人生 > >演算法和資料結構 --- 八種必須掌握的排序

演算法和資料結構 --- 八種必須掌握的排序

排序方法可以分為五種∶插入排序、選擇排序、交換排序、分配排序和歸併排序。
在排序過程中,全部記錄存放在記憶體,則稱為內排序,如果排序過程中需要使用外存,則稱為外排序。
首先來看一下八種排序之間的關係圖
8種排序關係圖

1、 直接插入排序

(1)基本思想:

在要排序的一組數中,假設前面(n-1) [n>=2] 個數已經是排好順序的,現在要把第n個數插到前面的有序數中,使得這n個數也是排好順序的。如此反覆迴圈,直到全部排好順序。

(2)理解圖:

已知待序的一組記錄的初始排列為:21, 25, 49, 25*, 16, 08
排序理解圖

開始排序
開始排序1

開始排序2

(3)程式碼實現

public
void insertSort(int[] a) { int i, j, temp; for (i = 1; i < a.length; i++) { temp = a[i]; // 把當前待比較項付給中間量 for (j = i; j > 0 && temp < a[j - 1]; j--) { // 如果待比較項小 a[j] = a[j - 1]; // 向後移 // 直到找到沒有比比較項大的就退出當前迴圈
} a[j] = temp;// 49 } for (i = 0; i < a.length; i++) { System.out.print(a[i] + "\t"); } }

直接插入排序最大的優點是簡單,在記錄數較少時,是比較好的辦法。

2、希爾排序(最小增量排序)

(1)基本思想:

演算法先將要排序的一組數按某個增量d(n/2,n為要排序數的個數)分成若干組,每組中記錄的下標相差d.對每組中全部元素進行直 接插入排序,然後再用一個較小的增量(d/2)對它進行分組,在每組中再進行直接插入排序。當增量減到1時,進行直接插入排序後,排序完成。

(2)理解圖

希爾排序理解圖

(3)程式碼實現

public void shellSort(int[] a) {
        int temp = 0;
        double d1 = a.length;
        while (true) {
            d1 = Math.ceil(d1 / 2);
            int d = (int) d1;

            for (int x = 0; x < d; x++) {
                for (int i = x + d; i < a.length; i += d) {
                    int j = i - d;
                    temp = a[i];
                    for (; j >= 0 && temp < a[j]; j -= d) {
                        a[j + d] = a[j];
                    }
                    a[j + d] = temp;
                }
            }
            if (d == 1) {
                break;
            }
        }
        for (int i = 0; i < a.length; i++)
            System.out.print(a[i] + "\t");
    }

3、簡單選擇排序

(1)基本思想:

在要排序的一組數中,選出最小的一個數與第一個位置的數交換; 然後在剩下的數當中再找最小的與第二個位置的數交換,如此迴圈到倒數第二個數和最後一個數比較為止。

(2)理解圖

簡單選擇排序1
簡單選擇排序2

第一次 : 08最小 和21交換位置
第二次: 除第一個位置的08外 16最小 和25交換位置
以此類推

(3)程式碼實現

 public static void selectSort(int[] a) {
        int position = 0;
        for (int i = 0; i < a.length; i++) {
            int j = i + 1;
            position = i;
            int temp = a[i];
            for (; j < a.length; j++) {
                if (a[j] < temp) {
                    temp = a[j];
                    position = j;
                }
            }
            a[position] = a[i];
            a[i] = temp;
        }
        for (int i = 0; i < a.length; i++)
            System.out.print(a[i] + "\t");
    }

4、堆排序

(1)基本思想:

堆排序是一種樹形選擇排序,是對直接選擇排序的有效改進。
堆的定義如下:具有n個元素的序列(h1,h2,…,hn),當且僅當滿足(hi>=h2i,hi>=2i+1)或(hi& lt;=h2i,hi<=2i+1)(i=1,2,…,n/2)時稱之為堆。在這裡只討論滿足前者條件的堆。
由堆的定義可以看出,堆頂元素(即第一 個元素)必為最大項(大頂堆)。完全二叉樹可以很直觀地表示堆的結構。
堆頂為根,其它為左子樹、右子樹。初始時把要排序的數的序列看作是一棵順序儲存的二 叉樹,調整它們的儲存序,使之成為一個堆,這時堆的根節點的數最大。然後將根節點與堆的最後一個節點交換。然後對前面(n-1)個數重新調整使之成為堆。 依此類推,直到只有兩個節點的堆,並對它們作交換,最後得到有n個節點的有序序列。
從演算法描述來看,堆排序需要兩個過程,一是建立堆,二是堆頂與堆的最後 一個元素交換位置。所以堆排序有兩個函式組成。一是建堆的滲透函式,二是反覆呼叫滲透函式實現排序的函式。

(2)例項:

初始序列:46,79,56,38,40,84

建堆:
堆排序-建堆

交換,從堆中踢出最大數
堆排序-交換

剩餘結點再建堆,再交換踢出最大數
堆排序-剩餘節點建堆交換

依次類推:最後堆中剩餘的最後兩個結點交換,踢出一個,排序完成。

(3)程式碼:

/**
 * 選擇排序之堆排序:
 * 
 * 1. 基本思想: 堆排序是一樹形選擇排序,在排序過程中,將R[1..N]看成是一顆完全二叉樹的順序儲存結構,
 * 利用完全二叉樹中雙親結點和孩子結點之間的內在關係來選擇最小的元素。
 * 
 * 2. 堆的定義: N個元素的序列K1,K2,K3,...,Kn.稱為堆,當且僅當該序列滿足特性: Ki≤K2i Ki ≤K2i+1(1≤ I≤[N/2])
 * 堆實質上是滿足如下性質的完全二叉樹:樹中任一非葉子結點的關鍵字均大於等於其孩子結點的關鍵字。例如序列10,15,56,25,30,70就是一個堆,
 * 它對應的完全二叉樹如上圖所示。這種堆中根結點(稱為堆頂)的關鍵字最小,我們把它稱為小根堆。
 * 反之,若完全二叉樹中任一非葉子結點的關鍵字均大於等於其孩子的關鍵字,則稱之為大根堆。
 * 
 * 3.排序過程: 堆排序正是利用小根堆(或大根堆)來選取當前無序區中關鍵字小(或最大)的記錄實現排序的。我們不妨利用大根堆來排序。每一趟排序的基本操作是:
 * 將當前無序區調整為一個大根堆
 * ,選取關鍵字最大的堆頂記錄,將它和無序區中的最後一個記錄交換。這樣,正好和直接選擇排序相反,有序區是在原記錄區的尾部形成並逐步向前擴大到整個記錄區。
 */
public class HeapSort {

    /**
     * 排序演算法的實現,對陣列中指定的元素進行排序
     * 
     * @param array
     *            待排序的陣列
     * @param c
     *            比較器
     */
    public void sort(Integer[] arr) {
        // 建立初始堆
        initialHeap(arr);

        /*
         * 對初始堆進行迴圈,且從最後一個節點開始,直到樹只有兩個節點止 每輪迴圈後丟棄最後一個葉子節點,再看作一個新的樹
         */
        for (int i = arr.length; i >= 2; i--) {
            // 根節點與最後一個葉子節點交換位置,即陣列中的第一個元素與最後一個元素互換
            swap(arr, 0, i - 1);
            // 交換後需要重新調整堆
            adjustNote(arr, 1, i - 1);
        }

    }

    /**
     * @param arr
     *            排序陣列
     * @param c
     *            比較器
     */
    private void initialHeap(Integer[] arr) {
        int lastBranchIndex = arr.length  / 2;// 最後一個非葉子節點
        // 對所有的非葉子節點進行迴圈 ,且從最後一個非葉子節點開始
        for (int i = lastBranchIndex; i >= 1; i--) {
            adjustNote(arr, i,  arr.length );
        }
    }

    /**
     * 調整節點順序,從父、左右子節點三個節點中選擇一個最大節點與父節點轉換
     * 
     * @param arr
     *            待排序陣列
     * @param parentNodeIndex
     *            要調整的節點,與它的子節點一起進行調整
     * @param len
     *            樹的節點數
     * @param c
     *            比較器
     */
    private void adjustNote(Integer[] arr, int parentNodeIndex, int len) {
        int maxValueIndex = parentNodeIndex;
        // 如果有左子樹,i * 2為左子樹節點索引
        if (parentNodeIndex * 2 <= len) {
            // 如果父節點小於左子樹時
            if ((arr[parentNodeIndex - 1]
                    .compareTo(arr[parentNodeIndex * 2 - 1])) < 0) {
                maxValueIndex = parentNodeIndex * 2;// 記錄最大索引為左子節點索引
            }
            // 只有在有左子樹的前提下才可能有右子樹,再進一步斷判是否有右子樹
            if (parentNodeIndex * 2 + 1 <= len) {
                // 如果右子樹比最大節點更大
                if ((arr[maxValueIndex - 1]
                        .compareTo(arr[(parentNodeIndex * 2 + 1) - 1])) < 0) {
                    maxValueIndex = parentNodeIndex * 2 + 1;// 記錄最大索引為右子節點索引
                }
            }
        }

        // 如果在父節點、左、右子節點三者中,最大節點不是父節點時需要交換,把最大的與父節點交換,建立大頂堆
        if (maxValueIndex != parentNodeIndex) {
            swap(arr, parentNodeIndex - 1, maxValueIndex - 1);
            // 交換後可能需要重建堆,原父節點可能需要繼續下沉  因為交換後 maxValueIndex位置的值就不一定是三個節點中最大的了! 
            if (maxValueIndex * 2 <= len) {// 是否有子節點,注,只需判斷是否有左子樹即可知道
                adjustNote(arr, maxValueIndex, len);
            }
        }
    }

    /**
     * 交換陣列中的兩個元素的位置
     * 
     * @param array
     *            待交換的陣列
     * @param i
     *            第一個元素
     * @param j
     *            第二個元素
     */
    public void swap(Integer[] array, int i, int j) {
        if (i != j) {// 只有不是同一位置時才需交換
            Integer tmp = array[i];
            array[i] = array[j];
            array[j] = tmp;
        }
    }

    /**
     * 測試
     * 
     * @param args
     */
    public static void main(String[] args) {
        Integer[] a = { 6,9,0,4,5, 9, 1, 4, 2, 6, 3, 8, 0, 7, 0, -7, -1, 34 };
        HeapSort heapsort = new HeapSort();
        heapsort.sort(a);
        for (Integer arrValue : a) {
            System.out.print(arrValue + " ");
        }
    }

}

5、氣泡排序

(1)基本思想:

在要排序的一組數中,對當前還未排好序的範圍內的全部數,自上而下對相鄰的兩個數依次進行比較和調整,讓較大的數往下沉,較小的往上冒。即:每當兩相鄰的數比較後發現它們的排序與排序要求相反時,就將它們互換。

(2)理解圖

氣泡排序1
氣泡排序2
氣泡排序3

(3)程式碼實現

/**
 * 氣泡排序是一種簡單的排序演算法。它重複地走訪過要排序的數列,一次比較兩個元素,
 * 如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重複地進行直到沒有再需要交換,
 * 也就是說該數列已經排序完成。
 * 這個演算法的名字由來是因為越小的元素會經由交換慢慢“浮”到數列的頂端。
 * 步驟:
 *    1、比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
      2、對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。
      3、針對所有的元素重複以上的步驟,除了最後一個。
      4、持續每次對越來越少的元素重複上面的步驟,直到沒有任何一對數字需要比較。
 * @author Administrator
 *
 */
public class bubbleSort {
    public bubbleSort() {
        int a[] = { 49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35,
                25, 53, 51 };
        int temp = 0;
        for (int i = 0; i < a.length - 1; i++) {
            for (int j = 0; j < a.length - 1 - i; j++) {
                if (a[j] > a[j + 1]) {
                    temp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = temp;
                }
            }
        }
        for (int i = 0; i < a.length; i++)
            System.out.println(a[i]);
    }
}

6、快速排序

(1)基本思想:

選擇一個基準元素,通常選擇第一個元素或者最後一個元素,通過一趟掃描,將待排序列分成兩部分,一部分比基準元素小,一部分大於等於基準元素,此時基準元素在其排好序後的正確位置,然後再用同樣的方法遞迴地排序劃分的兩部分。

(2)理解圖

快速排序1
快速排序2

(3)程式碼實現

/**
 * 快速排序是其基本思想是基本思想是,通過一趟排序將待排記錄分隔成獨立的兩部分,
 * 其中一部分記錄的關鍵字均比另一部分的關鍵字小,
 * 則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。
 * 步驟:
 *   1、從數列中挑出一個元素,稱為 "基準"(pivot),
     2、重新排序數列,所有元素比基準值小的擺放在基準前面,
        所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分割槽退出之後,
        該基準就處於數列的中間位置。這個稱為分割槽(partition)操作。
     3、遞迴地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。  
 * @author Administrator
 *
 */
public class QuickSort {

    public  void sort(){
        int a[] = { 11, 33, 44, 2, 0, 1, 49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17,
                18, 23, 34, 15, 35, 25, 53, 51, 90 };

        quickSort(a,0,a.length-1);
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i]+"  ");
        }

    }
    /**
     * 
     * @param a  待排序陣列
     * @param low  可以看做低位助手  
     * @param high 可以看做高位助手
     * 低助手是用來找比基準位大的數
     * 高助手是用來找比基準位小的數   這樣就可以看做兩個助手在活動
     */
    private  void quickSort(int[] a, int low, int high) {
        int start=low;//起始位置 0;
        int end=high; //結束位置
        int base=a[low]; //基準數 :一般是第一位
        int tempIndex=low; //找到的符合要求的位置:因為要把它的值付給基準數所在位置 所以要記錄該位置 可以看做是助手移動到的位置
        while(low<high){
            //高助手從右向左找一個比基準位小的數 找到後給到低助手當前所在位置
            //沒有找到的話 高助手向前移動一位
            while(low<high&&base<=a[high]){
                high--;
            }
            //找到時 把找到的數賦值給低助手所在位置
            a[low]=a[high];
            tempIndex=high;//記錄當前助手位置

            //然後低助手從左向右找一個比基準數大的數 ,找到後給到高助手當前所在位置
            //沒有找到的話 低助手向後移動一位
            while(low<high&&base>=a[low]){
                low++;
            }
            //找到後賦值給高助手當前所在位置
            a[high]=a[low];
            tempIndex=low;//記錄當前助手位置

            //直到迴圈結束  -->低助手和高助手重疊 就把基準數賦到當前中軸重疊位置
            a[tempIndex]=base;

        }
        //以上第一次排序結束  把數列分成了前後兩個部分
        //最後在對上面前後兩個部分數列 分別遞迴
        if(low-start>1){//前部分至少有兩個資料
            quickSort(a,0,low-1);
        }
        if(end-high>1){
            quickSort(a,high+1,end);
        }
    }

    public static void main(String[] args) {
        QuickSort q=new QuickSort();
        q.sort();
    }

}

7、歸併排序

(1)基本排序:

歸併(Merge)排序法是將兩個(或兩個以上)有序表合併成一個新的有序表,即把待排序序列分為若干個子序列,每個子序列是有序的。然後再把有序子序列合併為整體有序序列。

(2)理解圖:

遞迴分解:
遞迴分解

下面的圖理解合併
合併理解

(3)、實現程式碼

import java.util.Arrays;
/**
 * 歸併排序是建立在歸併操作上的一種有效的排序演算法。
 * 該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。
 * 歸併排序是一種穩定的排
 * 步驟:
    1、Divide: 把長度為n的輸入序列分成兩個長度為n/2的子序列。
    2、Conquer: 對這兩個子序列分別採用歸併排序。
    3、Combine: 將兩個排序好的子序列合併成一個最終的排序序列。
 * @author Administrator
 *
 */
public class mergineSort {
    int a[] = { 49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35, 25,
            53, 51 };

    public mergineSort() {
        sort(a, 0, a.length - 1);
        for (int i = 0; i < a.length; i++)
            System.out.println(a[i]);
    }
    /**
     * 
     * @param data 待排序陣列
     * @param left 陣列起始位置
     * @param right 陣列結束位置
     */
    public void sort(int[] data, int left, int right) {
        if (left < right) {//表明可以繼續拆分
            // 找出中間索引
            int center = (left + right) / 2;
            // 對左邊陣列進行遞迴
            sort(data, left, center);
            // 對右邊陣列進行遞迴
            sort(data, center + 1, right);
            // 合併
            merge(data, left, center, right);

        }
    }
    /**
     * 
     * @param data排序完的原陣列
     * @param left 起始位置
     * @param center 中間位置
     * @param right  結束位置
     */
    public void merge(int[] data, int left, int center, int right) {
        int[] tmpArr = new int[data.length];//中間臨時陣列
        int mid = center + 1;
        // temp記錄中間陣列的索引 -->就是合併這兩個陣列的大陣列的索引
        int temp = left;
        while (left <= center && mid <= right) {
            // 從兩個陣列中取出最小的放入中間陣列
            if (data[left] <= data[mid]) {
                tmpArr[temp] = data[left];
                left++;
                temp++;
            } else {
                tmpArr[temp] = data[mid];
                mid++;
                temp++;
            }
        }
        // 剩餘部分依次放入中間陣列(見上面的合併圖解)
        while (mid <= right) {
            tmpArr[temp] = data[mid];
            mid++;
            temp++;
        }
        while (left <= center) {
            tmpArr[temp] = data[left];
            left++;
            temp++;
        }
        // 將中間陣列中的內容複製回原陣列
        for(int i=0;i<=right;i++){
            data[i]=tmpArr[i];
        }
    }
}

8、基數排序

(1)基本思想:

將所有待比較數值(正整數)統一為同樣的數位長度,數位較短的數前面補零。然後,從最低位開始,依次進行一次排序。這樣從最低位排序一直到最高位排序完成以後,數列就變成一個有序序列。

(2)理解圖

基數排序理解

(3)實現程式碼

/**
 * 基數排序是一種非比較型整數排序演算法,其原理是將整數按位數切割成不同的數字,然後按每個位數分別比較。
 * 由於整數也可以表達字串(比如名字或日期)和特定格式的浮點數,
 * 所以基數排序也不是隻能使用於整數。
 * 步驟:
 *   1、將所有待比較數值(正整數)統一為同樣的數位長度,數位較短的數前面補零。
     2、從最低位開始,依次進行一次排序。
     3、這樣從最低位排序一直到最高位排序完成以後, 數列就變成一個有序序列。
 * @author Administrator
 *
 */
public class RadixSort {

    public static int[] radixSortAsc(int[] arr) {
        // 從低位往高位迴圈
        for (int d = 1; d <= getMax(arr); d++) {
            // 臨時陣列,用來存放排序過程中的資料
            int[] tmpArray = new int[arr.length];
            // 位記數器,從第0個元素到第9個元素依次用來記錄當前比較位是0的有多少個...是9的有多少個數
            int[] count = new int[10];
            // 開始統計0有多少個,並存儲在第0位,再統計1有多少個,並存儲在第1位..依次統計到9有多少個
            // { 73, 22, 93, 43, 55, 14, 28, 65, 39, 81, 33, 10 };
            for (int i = 0; i < arr.length; i++) {
                count[digit(arr[i], d)] += 1;// 統計該位上有多少個數字 比如第一位上0有多少個
            }
            /*
             * 比如某次經過上面統計後結果為:[0, 2, 3, 3, 0, 0, 0, 0, 0, 0]則經過下面計算後 結果為: [0, 2,
             * 5, 8, 8, 8, 8, 8, 8, 8]但實質上只有如下[0, 2, 5, 8, 0, 0, 0, 0, 0, 0]中
             * 非零數才用到,因為其他位不存在,它們分別表示如下:2表示比較位為1的元素可以存放在索引為1、0的
             * 位置,5表示比較位為2的元素可以存放在4、3、2三個(5-2=3)位置,8表示比較位為3的元素可以存放在
             * 7、6、5三個(8-5=3)位置
             */
            for (int i = 1; i < 10; i++) {
                count[i] += count[i - 1];
            }

            /*
             * 注,這裡只能從陣列後往前迴圈,因為排序時還需保持以前的已排序好的 順序,不應該打
             * 亂原來已排好的序,如果從前往後處理,則會把原來在前面會擺到後面去,因為在處理某個
             * 元素的位置時,位記數器是從大到到小(count[digit(arr[i], d)]--)的方式來處
             * 理的,即先存放索引大的元素,再存放索引小的元素,所以需從最後一個元素開始處理。
             * 如有這樣的一個序列[212,213,312],如果按照從第一個元素開始迴圈的話,經過第一輪
             * 後(個位)排序後,得到這樣一個序列[312,212,213],第一次好像沒什麼問題,但問題會
             * 從第二輪開始出現,第二輪排序後,會得到[213,212,312],這樣個位為3的元素本應該
             * 放在最後,但經過第二輪後卻排在了前面了,所以出現了問題
             */
            for (int i = arr.length - 1; i >= 0; i--) {// 只能從最後一個元素往前處理
                // for (int i = 0; i < arr.length; i++) {//不能從第一個元素開始迴圈
                tmpArray[count[digit(arr[i], d)] - 1] = arr[i];
                count[digit(arr[i], d)]--;
            }
            //System.arraycopy(tmpArray, 0, arr, 0, tmpArray.length);
            for(int i=0;i<arr.length;i++){
                arr[i]=tmpArray[i];
            }
        }
        return arr;
    }
    //求出最大數的位數的函式
    public static int getMax(int[] array) {
        // 取出最大數然後求出最大的位數
        int max = array[0];
        for (int j = 1; j < array.length; j++) {
            if (array[j] > max) {
                max = array[j];
            }
        }
        int time = 0;
        // 判斷位數;
        while (max > 0) {
            max /= 10;
            time++;
        }
        return time;
        // return String.valueOf(max).length();也可以根據字串長度返回
    }

    /**
     * 取數xxx上的第d位數字
     * 
     * @param x
     *            數字
     * @param d
     *            第幾位,從低位到高位
     * @return
     */
    public static int digit(int num, int d) {
        int pow = 1;
        while (--d > 0) {
            pow *= 10;
        }
        return num / pow % 10;
    }

    public static void main(String[] args) {
        int[] data = { 73, 22, 93, 43, 55, 14, 28, 65, 39, 81, 33, 10 };
        System.out.println(radixSortAsc(data));
        for (int i = 0; i < data.length; i++) {
            System.out.print(data[i] + " ");
        }
    }
}

相關推薦

演算法資料結構 --- 必須掌握排序

排序方法可以分為五種∶插入排序、選擇排序、交換排序、分配排序和歸併排序。 在排序過程中,全部記錄存放在記憶體,則稱為內排序,如果排序過程中需要使用外存,則稱為外排序。 首先來看一下八種排序之間的關係圖 1、 直接插入排序 (1)基本思想:

淺談演算法資料結構: 平衡查詢樹之2-3樹

前面介紹了二叉查詢樹(Binary Search Tree),他對於大多數情況下的查詢和插入在效率上來說是沒有問題的,但是他在最差的情況下效率比較低。本文及後面文章介紹的平衡查詢樹的資料結構能夠保證在最差的情況下也能達到lgN的效率,要實現這一目標我們需要保證樹在插入完成之後

查詢演算法 淺談演算法資料結構: 七 二叉查詢樹 淺談演算法資料結構: 十一 雜湊表

閱讀目錄 1. 順序查詢 2. 二分查詢 3. 插值查詢 4. 斐波那契查詢 5. 樹表查詢 6. 分塊查詢 7. 雜湊查詢   查詢是在大量的資訊中尋找一個特定的資訊元素,在計算機應用中,查詢是常用的基本運算,例如編譯程式中符號表的查詢。本文

淺談演算法資料結構: 五 優先順序佇列與堆排序

在很多應用中,我們通常需要按照優先順序情況對待處理物件進行處理,比如首先處理優先順序最高的物件,然後處理次高的物件。最簡單的一個例子就是,在手機上玩遊戲的時候,如果有來電,那麼系統應該優先處理打進來的電話。 在這種情況下,我們的資料結構應該提供兩個最基本的操作,一個是返回最高優先

拒絕調包俠,不需要高階演算法資料結構技巧

前言 大多數工科學生或者剛剛入門近年來比較火的“人工智慧”相關演算法的同學,在選擇語言的時候,都會選擇MATLAB、Python、R等等這些高階語言,對自己所學的演算法進行實現和除錯。這些高階語言中,包含了實現複雜演算法的基礎數學演算法、基本統計演算法、基礎資料結構的實現,比如均值(mean)、方差(std

java中各種演算法資料結構的使用場景

一。通用資料結構:陣列,連結串列,樹,雜湊表 通用資料結構通過關鍵字的值來儲存並查詢資料,如報表,合同,記錄,業績等資料。通用資料結構可以用速度的快慢來分類,陣列和連結串列是最慢的,樹相對較快,雜湊表是最快的。請注意,並不是最快的就一定是最好的,因為最快的結構的

淺談演算法資料結構: 九 平衡查詢樹之紅黑樹

前面一篇文章介紹了2-3查詢樹,可以看到,2-3查詢樹能保證在插入元素之後能保持樹的平衡狀態,最壞情況下即所有的子節點都是2-node,樹的高度為lgN,從而保證了最壞情況下的時間複雜度。但是2-3樹實現起來比較複雜,本文介紹一種簡單實現2-3樹的資料結構,即紅黑樹(

演算法資料結構

資料結構 堆 長度為n的陣列構建成最小堆的時間複雜度 B、B+樹、紅黑樹 說一下B+樹和二叉搜尋樹的區別? 說一下二叉搜尋樹和AVL樹、紅黑樹之間的差別 說下紅黑樹原理,紅黑樹你看虛擬碼的時候他有兩坨比較一樣的有沒有注意過 哪些情況下用棧 知道雜湊嗎?二叉樹比

演算法資料結構單鏈表的逆轉

public void reverse(SinglyList<T> list) { Node<T> p = list.head.next, succ = null, front = null; while (p != null) {

淺談演算法資料結構: 十 平衡查詢樹之B樹

前面講解了平衡查詢樹中的2-3樹以及其實現紅黑樹。2-3樹種,一個節點最多有2個key,而紅黑樹則使用染色的方式來標識這兩個key。 維基百科對B樹的定義為“在電腦科學中,B樹(B-tree)是一種樹狀資料結構,它能夠儲存資料、對其進行排序並允許以O(log n)的時間複雜度執行進行查詢、順序讀取、插入和刪

演算法資料結構】平衡查詢樹之B樹

  以B-樹的效能總是等價於二分查詢(與M值無關),也就沒有B樹平衡的問題;由於M/2的限制,在插入結點時,如果結點已滿,需要將結點分裂為兩個各佔M/2的結點;刪除結點時,需將兩個不足M/2的兄弟結點合併。 下面簡單說明分裂:    下面對B-樹進行實現 #pragma once //3階B樹 tem

挑戰程式設計競賽 演算法資料結構 第6章 遞迴分治法

仿照上述程式碼,本人編寫的C語言AC程式碼如下: //ALDS1_5_C:Koch Curve //2一個很致命的問題,將遞迴中的 s,t;區域性變數寫成全域性變數 //深刻感覺遞迴,還需要時間的積累。2017-9-29 AC #include <stdio.h> #include <ma

python演算法資料結構筆記--漢諾塔問題超詳細遞迴過程圖解(堆疊資料結構

兩個盤子時:1移動到B,2移動到A,1移動到C N個盤子時:n-1移動到B,n移動到A,n-1移動到C 3個盤子為例子,如何將問題歸納為同類的子問題 我們的目標是的第一步先將1,2號盤子移動到B 當3號盤不存在,把B,C柱換個位置,問題轉化為將2個盤子藉助C移動到B子的問題。 要將1,2

《常見演算法資料結構》優先佇列(2)——二叉堆

二叉堆 本系列文章主要介紹常用的演算法和資料結構的知識,記錄的是《Algorithms I/II》課程的內容,採用的是“演算法(第4版)”這本紅寶書作為學習教材的,語言是java。這本書的名

演算法資料結構書籍推薦

資料結構 資料結構與演算法分析_Java語言描述(第2版) 演算法 計算機演算法基礎 演算法導論 程式設計之法_面試和演算法心得 coding 程式設計師程式碼面試指南_IT名企演算法與資料結構題目最優解 LeetCode/LintCode

挑戰程式設計競賽2 演算法資料結構 讀後感

介紹 本篇主要是講《挑戰程式設計競賽2 演算法和資料結構》書的讀後感和部分題目的再次解讀、程式設計。包括書中的部分程式碼和一些個人的見解。如果想深入瞭解,建議去網上買一本回來看,比較適合學習演算法的初學者。 章節 第一章 第一章主要

為什麼要學習演算法資料結構

這裡有一些想法。可能你會發現這個問題在任何演算法書的序言中回答,但無論如何,這是我的看法。 1)不受資料結構程式語言的約束 沒有對各種資料結構的瞭解,很容易限制在語言直接提供的資料結構方面思考解決方案。 如果您是Java程式設計師,您可能會考慮解決方案,只

《常見演算法資料結構》優先佇列(3)——堆排序

堆排序 本系列文章主要介紹常用的演算法和資料結構的知識,記錄的是《Algorithms I/II》課程的內容,採用的是“演算法(第4版)”這本紅寶書作為學習教材的,語言是java。這本書的名

【 專欄 】- 演算法資料結構C++實現

演算法和資料結構C++實現 用C++實現各種資料結構和演算法,包括書本《演算法導論》《資料結構-嚴蔚敏》《演算法設計與分析》等的例子,和麵試常用演算法,經典演算法等。 本專欄注重C++語言特徵,包括STL的用法。

(筆記)如何快速攻破傳統演算法資料結構

知乎上的SimonS大神的講座,給想學習演算法的童鞋的一些建議: https://www.zhihu.com/lives/795264798257479680 一,QA部分: 1. 985 大二 專業軟工 沒有oi經歷。如何一年時間拿到ACM區預賽銀牌? 主要參考後續的