[golang] 資料結構-快速排序

來源:互聯網
上載者:User

快速排序是個非常經典、高效、常用的排序演算法。很多語言標準庫裡的排序演算法都有用到它。

原理
快排原理其實比較簡單,就是將原本很大的數組拆成小數組去解決問題。
要拆就得找個拆的位置。如果吧這個位置稱為支點,那麼快速排序問題就變成了不斷的去找到拆分的支點元素位置。
通常找支點就是以某個元素為標準,分別從最右側元素向左找到比指定元素小的位置,再從最左側開始向右找比指定元素大的位置。如果兩個位置不相同就交換兩個位置,在繼續分表從兩頭相向尋找。找到合適的位置就是我們需要的支點。支點兩邊的元素再各自重複上面的操作,直到分拆出來的子數組只剩一個元素。分拆結束,順序也就拍好了。
那麼問題來了,以哪個元素為標準去比較呢?比如可以選第一個元素。

複雜度
理想情況下找到的支點可以把數組拆分成左右長度相近的子數組,此時時間複雜度為O(n*logn)
而最差情況則是每次找到的支點元素都在某一次,導致另一側完全浪費,尋找支點的過程也浪費。這個時候用時會達到O(n^2)。
由於會打亂相同元素原有的順序,所以快排也是一個不穩定排序。所以常用在普通類型資料的排序中。

代碼實現

package mainimport (    "time"    "fmt"    "math/rand")func main() {    var length = 10    var list []int    // 以時間戳記為種子產生隨機數,保證每次運行資料不重複    r := rand.New(rand.NewSource(time.Now().UnixNano()))    for i := 0; i < length; i++ {        list = append(list, int(r.Intn(50)))    }    fmt.Println(list)    quickSort(list, 0, length-1)    fmt.Println(list)}func quickSort(list []int, start, end int) {    // 只剩一個元素時就返回了    if start >= end {        return    }    // 標記最左側元素作為參考    tmp := list[start]    // 兩個遊標分別從兩端相向移動,尋找合適的"支點"    left := start    right := end    for left != right {        // 右邊的遊標向左移動,直到找到比參考的元素值小的        for list[right] >= tmp && left < right {            right--        }        // 左側遊標向右移動,直到找到比參考元素值大的        for list[left] <= tmp && left < right {            left++        }        // 如果找到的兩個遊標位置不統一,就遊標位置元素的值,並繼續下一輪尋找        // 此時交換的左右位置的值,右側一定不大於左側。可能相等但也會交換位置,所以才叫不穩定的排序演算法        if left < right {            list[left], list[right] = list[right], list[left]            fmt.Println(list)        }    }    // 這時的left位置已經是我們要找的支點了,交換位置    list[start], list[left] = list[left], tmp    // 按支點位置吧原數列分成兩段,再各自逐步縮小範圍排序    quickSort(list, start, left-1)    quickSort(list, left+1, end)}

運行結果

雜談
遇到最差情況時,上面演算法的效能就比較糟糕了,和普通的插入排序差不多。所以為了避免選了個糟糕的支點,可以選擇數組中間元素作為對比的標準,或是選3個元素,取中間大小的元素作為參考項。這時可以在一定程度上最佳化效能。不過最快情況的情境是在太少見,基本可以忽略掉。
還有個可最佳化的點,就是在資料量很少時,快排並不能體現速度優勢,反而在二十幾個元素以內的排序中比插入排序還慢。所以可以在遞迴迴圈裡加個判斷,如果一側的元素數量小於某個值(比如20)時直接使用插入排序。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.