1. 程式人生 > >資料結構與算法系列十(排序演算法概述)

資料結構與算法系列十(排序演算法概述)

1.引子

1.1.為什麼要學習資料結構與演算法?

有人說,資料結構與演算法,計算機網路,與作業系統都一樣,脫離日常開發,除了面試這輩子可能都用不到呀!

有人說,我是做業務開發的,只要熟練API,熟練框架,熟練各種中介軟體,寫的程式碼不也能“飛”起來嗎?

於是問題來了:為什麼還要學習資料結構與演算法呢?

#理由一:
    面試的時候,千萬不要被資料結構與演算法拖了後腿
#理由二:
    你真的願意做一輩子CRUD Boy嗎
#理由三:
    不想寫出開源框架,中介軟體的工程師,不是好廚子

1.2.如何系統化學習資料結構與演算法?

我想好了,還是需要學習資料結構與演算法。但是我有兩個困惑:

1.如何著手學習呢?

2.有哪些內容要學習呢?

學習方法推薦:

#學習方法
1.從基礎開始,系統化學習
2.多動手,每一種資料結構與演算法,都自己用程式碼實現出來
3.思路更重要:理解實現思想,不要背程式碼
4.與日常開發結合,對應應用場景

學習內容推薦:

資料結構與演算法內容比較多,我們本著實用原則,學習經典的、常用的資料結構、與常用演算法

#學習內容:
1.資料結構的定義
2.演算法的定義
3.複雜度分析
4.常用資料結構
    陣列、連結串列、棧、佇列
    散列表、二叉樹、堆
    跳錶、圖
5.常用演算法
    遞迴、排序、二分查詢
    搜尋、雜湊、貪心、分治
    動態規劃、字串匹配

2.考考你

在前面兩篇,我們詳細看了常用演算法的第一個主題:遞迴。接下來我們來看常用演算法的第二個主題:排序。排序內容有點多,常見的排序演算法就有:氣泡排序、插入排序、選擇排序、歸併排序、快速排序、桶排序、計數排序、基數排序。

這些排序演算法中,不知道有沒有你熟悉的,或者不熟悉的。讓我們開啟排序演算法之旅吧。首先第一篇中,我們先來對排序演算法做一個總體上的認識。

#考考你:
1.你知道常用的排序演算法有哪些嗎?
2.你知道如何衡量排序演算法的優劣嗎?
3.你知道排序演算法的基礎概念:有序度、逆序度、滿有序度嗎?

3.案例

3.1.排序演算法分類

在考考你中,我們說排序演算法有:氣泡排序、插入排序、選擇排序、歸併排序、快速排序、桶排序、計數排序、基數排序。這樣看起來有點散亂,能不能給它們歸一下類呢?答案是可以的。

對於排序演算法,我們可以從時間複雜度上進行歸類:

 

 

 

3.2.從三個角度分析排序演算法

在實際軟體開發中,有眾多的排序演算法,如何選擇和取捨呢?真的會有選擇困難症啊!有沒有一些好的、可行的方法,去綜合衡量排序演算法的優劣呢?

答案是:有

我們可以從三個角度去綜合分析排序演算法:時間複雜度、空間複雜度、演算法穩定性

#時間複雜度
  1.分析最好情況、最壞情況、平均情況時間複雜度
  2.複雜度分析中,關於係數、常數、低階平常可以省略
  3.但是,需要特別注意:在排序演算法中,我們需要考慮進來

#空間複雜度
  1.空間複雜度分析,主要看是否是:原地排序演算法
  2.原地排序演算法,是指:空間複雜度是O(1)
  3.注意:在實際軟體開發中,這一條很重要

#演算法穩定性
  1.演算法穩定性,是指如果待排序序列中,有值相同的元素
  2.如果經過排序後,原來值相同的元素,順序保持不變
  3.那麼我們說,該排序演算法是穩定的排序演算法
  4.否則,該排序演算法是不穩定排序演算法
  
  5.比如,有一個待排序序列:3,6,5,2,6,8
  6.待排序序列中,有兩個值為6的元素
  7.假設用陣列a來儲存,對應的下標是:a[1]=6,a[4]=6
  8.排序後:a[3]=6,a[4]=6
  9.這裡的a[3]是排序前的a[1]
  10.這裡的a[4]還是排序前的a[4]
  11.這就是穩定排序演算法的要求,如下圖:

理解排序演算法穩定性:

 

 

3.3.排序基礎概念:有序度、逆序度、滿有序度

在排序演算法中,我們需要關注三個基礎概念:有序度、逆序度、滿有序度。

整個排序過程,我們可以理解為:增加有序度,減少逆序度,最終達到滿有序度的過程。

那麼,它們具體的含義是什麼呢?

#有序度:
  待排序序列中,如果下標索引:i<j,且a[i]<a[j],則稱為有序度
#逆序度
  待排序序列中,如果下標索引:i<j,且a[i]>a[j],則稱為逆序度
#滿有序度
  1.待排序序列中,如果有序度達到:n(n-1)/2,則稱為滿有序度
  2.即此時待排序序列,其實是有序的

以上關於有序度、逆序度的概念,相信很多朋友都能理解。這裡我們解釋一下關於滿有序度的公式:n(n-1)/2。

要理解滿有序度的概念,你可能需要回顧一下數學中的:排列、組合知識點,應該是在高二的時候學的,可以這樣去理解它們:

#排列:
  1.有n個元素,如果每兩個元素,組成一個排列
  2.則總共有排列數:n(n-1)
  3.比如,有3個元素:a b c
  4.每兩個元素組成排列數是:3*(3-1)=6
  5.組成的排列有:(a,b) (a,c) (b,a) (b,c) (c,a) (c,b)
  
#組合:
  1.有n個元素,如果每兩個元素,組成一個組合
  2.則總共有組合數:n(n-1)/2
  3.比如,有3個元素:a b c
  4.每兩個元素組成的組合數是:3(3-1)/2=3
  5.組成的組合有:(a,b) (a,c) (b,c)
  
#綜合結論:
   1.假設待排序序列有n個元素
   2.如果有序度,等於每2個元素的組合數:n(n-1)/2
   3.那麼該待排序序列,其實是有序的
   4.這就是滿有序度的概念

&n