資料結構與算法系列十三(選擇排序)
阿新 • • 發佈:2020-04-01
1.引子
1.1.為什麼要學習資料結構與演算法?
有人說,資料結構與演算法,計算機網路,與作業系統都一樣,脫離日常開發,除了面試這輩子可能都用不到呀!
有人說,我是做業務開發的,只要熟練API,熟練框架,熟練各種中介軟體,寫的程式碼不也能“飛”起來嗎?
於是問題來了:為什麼還要學習資料結構與演算法呢?
#理由一: 面試的時候,千萬不要被資料結構與演算法拖了後腿 #理由二: 你真的願意做一輩子CRUD Boy嗎 #理由三: 不想寫出開源框架,中介軟體的工程師,不是好廚子
1.2.如何系統化學習資料結構與演算法?
我想好了,還是需要學習資料結構與演算法。但是我有兩個困惑:
1.如何著手學習呢?
2.有哪些內容要學習呢?
學習方法推薦:
#學習方法 1.從基礎開始,系統化學習 2.多動手,每一種資料結構與演算法,都自己用程式碼實現出來 3.思路更重要:理解實現思想,不要背程式碼 4.與日常開發結合,對應應用場景
學習內容推薦:
資料結構與演算法內容比較多,我們本著實用原則,學習經典的、常用的資料結構、與常用演算法
#學習內容: 1.資料結構的定義 2.演算法的定義 3.複雜度分析 4.常用資料結構 陣列、連結串列、棧、佇列 散列表、二叉樹、堆 跳錶、圖 5.常用演算法 遞迴、排序、二分查詢 搜尋、雜湊、貪心、分治 動態規劃、字串匹配
2.考考你
上一篇:資料結構與算法系列十二(插入排序)中,我們詳細分析了插入排序的核心思想,和程式碼實現。插入排序的核心思想很巧妙:它是將待排序序列,分為有序區間,和無序區間,迴圈遍歷無序區間,每一次將無序區間中的第一個元素,插入到有序區間的合適位置,每一次插入都要始終保證有序區間有序。
你需要對插入排序的核心思想再仔細琢磨一下,因為我們今天的主角:選擇排序,它的核心思想與插入排序類似。
#考考你: 1.你知道選擇排序的核心思想嗎? 2.你能用java程式碼實現選擇排序嗎? 3.你知道實際開發中,為什麼插入排序,比選擇排序更好嗎?
3.案例
3.1.選擇排序核心思想
假設有一個待排序序列:[4, 5, 6, 3, 2, 1]。我們需要按照升序進行排序,排序後的序列是這 樣的:[1, 2, 3, 4, 5, 6]。
如何通過選擇排序實現呢?
選擇排序核心思想:
將待排序序列,分成兩個區間:有序區間、無序區間。一開始假定有序區間元素個數:0,無序區間元素個數:n。迴圈遍歷無序區間,每一次從無序區間中,選擇最小的一個元素,插入到有序區間的末尾。
這裡的關鍵詞有:
1.待排序序列,分成:有序區間、無序區間 2.最開始,假定有序區間元素個數:0,無序區間元素個數:n 3.每次迴圈遍歷無序區間,選擇最小元素,插入到有序區間末尾,如下圖:
3.2.選擇排序程式碼實現
3.2.1.排序程式碼
/** * 選擇排序 * @param array:待排序陣列 * @param n:待排序陣列大小 */ public static void sort(Integer [] array,int n) { // 如果排序陣列規模小於等於1,直接返回 if (n <= 1) { return; } // 將待排序陣列,分為:有序區間、無序區間 // 一開始,假設整個序列都無序,那麼有序區間的元素個數是:0 // 無序區間的元素個數是:n // 每次從無序區間中,選擇最小元素 // 插入有序區間末尾:n個元素,n次選擇 for(int i = 0; i < n; i++){ // 從無序區間第一個位置開始查詢:最小元素位置 int min = i; for(int j = i+1; j < n; j++){ // 比較大小,設定新的最小元素位置標記 if(array[min] > array[j]){ min = j; } } // 找到新的最小元素位置後,進行資料交換 System.out.println("第【"+(i+1)+"】次選擇,最小元素是:"+array[min]); int tmp = array[i]; array[i] = array[min]; array[min] = tmp; } }
3.2.2.測試程式碼
/** * 選擇排序: * 1.時間複雜度: * O(n^2) * 2.空間複雜度: * O(1)是原地排序演算法 * 3.演算法穩定性: * 不是穩定排序演算法 */ public static void main(String[] args) { // 初始化測試陣列 Integer[] array = {4,5,6,3,2,1}; // 排序前 System.out.println("1.排序前陣列:" + Arrays.deepToString(array)); // 排序 System.out.println("2.開始排序-------------------------------start"); sort(array,array.length); // 排序後 System.out.println("3.排序後陣列:" + Arrays.deepToString(array)); }
測試結果:
D:\02teach\01soft\jdk8\bin\java com.anan.algorithm.sort.SelectSort 1.排序前陣列:[4, 5, 6, 3, 2, 1] 2.開始排序-------------------------------start 第【1】次選擇,最小元素是:1 第【2】次選擇,最小元素是:2 第【3】次選擇,最小元素是:3 第【4】次選擇,最小元素是:4 第【5】次選擇,最小元素是:5 第【6】次選擇,最小元素是:6 3.排序後陣列:[1, 2, 3, 4, 5, 6] Process finished with exit code 0
4.討論分享
#考考你答案: 1.你知道選擇排序的核心思想嗎? 1.1.將待排序序列,分成:有序區間、無序區間 1.2.最開始,有序區間元素個數:0,無序區間元素個數:n 1.3.迴圈遍歷無序區間,每次選擇最小元素,插入有序區間末尾 2.你能用java程式碼實現選擇排序嗎? 2.1.參考【3.2】節程式碼實現 3.你知道實際開發中,為什麼插入排序,比選擇排序更好嗎? 3.1.我們在排序演算法概述中說過,衡量一個排序演算法的優劣, 有三個因素:時間複雜度、空間複雜度、是否穩定 3.2.插入排序與選擇排序,它們的時間複雜度都是:O(n^2) 3.3.插入排序與選擇排序,它們的空間複雜度都是:O(1) 3.3.插入排序,是穩定的排序演算法 3.4.【注意】:選擇排序,不是穩定排序演算法 3.5.假設有一個待排序序列:int a[]={4,5,6,4,3,2,1} 3.6.待排序序列中,有重複元素:a[0]=4,a[3]=4 3.7.第一輪選擇排序,選擇最小元素:a[6]=1 3.8.將a[0]=4,a[6]=1進行交換 3.9.【注意】:第一輪選擇排序後,重複元素4的順序發生了改變 3.10.待排序序列變成:a[]={1,5,6,4,3,2,4} 3.11.此時重複元素:a[3]=4,a[6]=4 3.12.a[3]還是原來的a[3],a[6]是原來的a[0] 3.13.我們說穩定排序演算法,是指待排序序列中重複元素, 排序前的順序,與排序後的順序保持不變 3.14.可見選擇排序,不符合穩定排序演算法的定義 3.15.關於選擇排序,不是穩定排序演算法的分析,你可以結合我們前面的圖來理解
&n