成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

程序猿修仙之路--算法之快速排序到底有多快

felix0913 / 2632人閱讀

摘要:可見快速排序不是穩(wěn)定的排序。在這種小數(shù)組的情況下,其實一些基礎排序算法反而比快速排序要快。當一個數(shù)組為無序并且重復元素不多時候,也適合快速排序。

分治思想
關于排序,江湖盛傳有一種分治思想,能大幅度提高排序心法的性能。所謂分治,即:化大為小,分而治之。達到治小而治大的成效。多年來基于分治思想衍生出多種排序心法,然萬變不離其宗!

雖然江湖上算法內功繁多,但是好的算法小編認為必須符合以下幾個條件,方能真正提高習練者實力。

時間復雜度(運行時間)

在算法時間復雜度維度,我們主要對比較和交換的次數(shù)做對比,其他不交換元素的算法,主要會以訪問數(shù)組的次數(shù)的維度做對比。

其實有很多修煉者對于算法的時間復雜度有點模糊,分不清什么所謂的 O(n),O(nlogn),O(logn)...等,也許下圖對一些人有一些更直觀的認識。

空間復雜度(額外的內存使用)

排序算法的額外內存開銷和運行時間同等重要。 就算一個算法時間復雜度比較優(yōu)秀,空間復雜度非常差,使用的額外內存非常大,菜菜認為它也算不上一個優(yōu)秀的算法。

結果的正確性

這個指標是菜菜自己加上的,我始終認為一個優(yōu)秀的算法最終得到的結果必須是正確的。就算一個算法擁有非常優(yōu)秀的時間和空間復雜度,但是結果不正確,導致修煉者經(jīng)脈逆轉,走火入魔,又有什么意義呢?
原理
基本思想:選取一個元素作為分割點,通過遍歷把小于分割點的元素放到分割點左邊,把大于分割點的元素放到分割點元素右邊。然后再按此方法對兩部分數(shù)據(jù)分別排序,以此類推,直到分割的數(shù)組大小為1。 整個排序過程可以遞歸進行,以此達到整個數(shù)據(jù)變成有序序列。
過程

實現(xiàn)快速排序的方式有很多,其中以類似指針移動方式最為常見,為什么最常見呢?因為它的空間復雜度為O(1),也就是說是原地排序。

我們從待排序的記錄序列中選取一個記錄(通常第一個)作為基準元素(稱為key)key=arr[left],然后設置兩個變量,left指向數(shù)列的最左部,right指向數(shù)據(jù)的最右部。

key首先與arr[right]進行比較,如果arr[right]key則我們只需要將right--,right--之后,再拿arr[right]與key進行比較,直到arr[right]

如果右邊存在arr[right]key,則將arr[right]=arr[left],如果arr[left]

然后再移動right重復上述步驟

最后得到 {23 58 13 10 57 62} 65 {106 78 95 85},再對左子數(shù)列與右子數(shù)列進行同樣的操作。最終得到一個有序的數(shù)列。

{23 58 13 10 57 62} 65 {106 78   95 85}
{10 13} 23 {58 57 62} 65 {85 78 95} 106
10 13 23 57 58 62 65 78 85 95 106
性能特點
關于復雜度相關O(n)等公式,我這里需要強調一點,公式代表的是算法的復雜度增長的趨勢,而不是具體計算復雜度的公式。比如:O(n2)和O(n)相比較,只是說明 O(n2)增長的趨勢要比o(n)快,并不是說明O(n2)的算法比O(n)的算法所用時間一定就要多。
時間復雜度

快速排序平均時間復雜度為O(nlogn),最好情況下為O(nlogn),最壞情況下O(n2)

空間復雜度

基于以上例子來實現(xiàn)的快排,空間復雜度為O(1),也就是原地排序。

穩(wěn)定性

舉個例子:
待排序數(shù)組:int a[] ={1, 2, 2, 3, 4, 5, 6};

在快速排序的隨機選擇比較子(即pivot)階段:
若選擇a[2](即數(shù)組中的第二個2)為比較子,,而把大于等于比較子的數(shù)均放置在大數(shù)數(shù)組中,則a[1](即數(shù)組中的第一個2)會到pivot的右邊, 那么數(shù)組中的兩個2非原序(這就是“不穩(wěn)定”)。
若選擇a[1]為比較子,而把小于等于比較子的數(shù)均放置在小數(shù)數(shù)組中,則數(shù)組中的兩個2順序也非原序。可見快速排序不是穩(wěn)定的排序。

改進

通過以上分析各位俠士是否能夠分析出來快速排序有哪些地方存在瑕疵呢?

切分不平衡:也就是說我們選取的切分元素距離數(shù)組中間值的元素位置很遠,極端情況下會是數(shù)組最大或最小的元素,這就導致了劃分出來的大數(shù)組會被劃分為很多次。針對此情況,我們可以取數(shù)組多個元素來平衡這種情況,例如:我們可以隨機選取三個或者五個元素,取其中間值的元素作為分割元素。

小數(shù)組:當快速排序切分為比較小的數(shù)組時候,也會利用遞歸調用自己。在這種小數(shù)組的情況下,其實一些基礎排序算法反而比快速排序要快。當數(shù)組比較小的時候不妨嘗試一下切換到插入排序。具體多小是小呢?一般5-15吧,僅供參考。

重復元素:在我們實際應用中經(jīng)常會遇到重復元素比較多的情況,按照快排的思想,相同元素是會被頻繁移動和劃分的,其實這完全沒有必要。我們該怎么辦呢?我們可以把數(shù)組切換為三部分:大于-等于-小于 三部分數(shù)組,這樣等于的那部分數(shù)組就可以避免移動了,不過落地的代碼復雜度要高很多,有興趣的同學可以實現(xiàn)一下。

使用場景

當一個數(shù)組大小為中型以上的數(shù)量級時,菜菜認為可以使用快速排序,并且伴隨著數(shù)組的持續(xù)增大,快速排序的性能趨于平均運行時間。至于多大的數(shù)組為中型,一般認為50+ 吧,僅供參考。

當一個數(shù)組為無序并且重復元素不多時候,也適合快速排序。為什么提出重復元素這個點呢?因為如果重復元素過多,本來重復元素是無需排序的,但是快速排序還是要劃分為更多的子數(shù)組來比較,這個時候也許插入排序更適合。

試煉一發(fā)吧
c# 武器版
        static void Main(string[] args)
        {
            List data = new List();
            for (int i = 0; i < 11; i++)
            {

                data.Add(new Random(Guid.NewGuid().GetHashCode()).Next(1, 100));
            }
            //打印原始數(shù)組值
            Console.WriteLine($"原始數(shù)據(jù): {string.Join(",", data)}");
            quickSort(data, 0, data.Count - 1);
            //打印排序后的數(shù)組
            Console.WriteLine($"排序數(shù)據(jù): {string.Join(",", data)}");
            Console.Read();
        }
        public static void quickSort(List  source, int left, int right)
        {
            int pivot = 0;
            if (left < right)
            {
                pivot = partition(source, left, right);
                quickSort(source, left, pivot - 1);
                quickSort(source, pivot + 1, right);
            }
        }
        //對一個數(shù)組/列表按照第一個元素 分組排序,返回排序之后key所在的位置索引
        private static int partition(List source, int left, int right)
        {
            int key = source[left];
            while (left < right)
            {
                //從右邊篩選 大于選取的值的不動,小于key的交換位置
                while (left < right && source[right] >= key)
                {
                    right--;
                }
                source[left] = source[right];
                while (left < right && source[left] <= key)
                {
                    left++;
                }
                source[right] = source[left];
            }
            source[left] = key;
            return left;
        }
golang 武器版
package main

import (
    "fmt"
    "math/rand"
)

func main() {
    var data []int
    for i := 0; i < 10; i++ {
        data = append(data, rand.Intn(100))
    }
    fmt.Println(data)
    quickSort(data[:], 0, len(data)-1)
    fmt.Println(data)
}
func quickSort(source []int, left int, right int) {
    var pivot = 0
    if left < right {
        pivot = partition(source, left, right)                                        
        quickSort(source, left, pivot-1)
        quickSort(source, pivot+1, right)
    }
}

func partition(source []int, left int, right int) int {
    var key = source[left]
    for left < right {
        for left < right && source[right] >= key {
            right--
        }
        source[left] = source[right]
        for left < right && source[left] <= key {
            left++
        }
        source[right] = source[left]
    }
    source[left] = key
    return left
}

運行結果:

[81 87 47 59 81 18 25 40 56 0]
[0 18 25 40 47 56 59 81 81 87]

添加關注,查看更精美版本,收獲更多精彩

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://systransis.cn/yun/31329.html

相關文章

  • 程序修仙--算法快速排序到底多快

    摘要:可見快速排序不是穩(wěn)定的排序。在這種小數(shù)組的情況下,其實一些基礎排序算法反而比快速排序要快。當一個數(shù)組為無序并且重復元素不多時候,也適合快速排序。 分治思想 關于排序,江湖盛傳有一種分治思想,能大幅度提高排序心法的性能。所謂分治,即:化大為小,分而治之。達到治小而治大的成效。多年來基于分治思想衍生出多種排序心法,然萬變不離其宗!雖然江湖上算法內功繁多,但是好的算法小編認為必須符合以下幾...

    trigkit4 評論0 收藏0
  • 用 PHP 的方式實現(xiàn)的各類算法合集

    摘要:數(shù)據(jù)項是數(shù)據(jù)的不可分割的最小單位。數(shù)據(jù)項是對客觀事物某一方面特性的數(shù)據(jù)描述。數(shù)據(jù)對象是性質相同的數(shù)據(jù)元素的集合,是數(shù)據(jù)的一個子集。數(shù)據(jù)的邏輯結構數(shù)據(jù)元素之間的相互關系稱為邏輯結構。 項目地址 https://github.com/m9rco/algo... 每周最少一更,求出題,求虐待 At least once a week, ask for problems and abuse 簡...

    Karrdy 評論0 收藏0
  • 用 PHP 的方式實現(xiàn)的各類算法合集

    摘要:數(shù)據(jù)項是數(shù)據(jù)的不可分割的最小單位。數(shù)據(jù)項是對客觀事物某一方面特性的數(shù)據(jù)描述。數(shù)據(jù)對象是性質相同的數(shù)據(jù)元素的集合,是數(shù)據(jù)的一個子集。數(shù)據(jù)的邏輯結構數(shù)據(jù)元素之間的相互關系稱為邏輯結構。 項目地址 https://github.com/m9rco/algo... 每周最少一更,求出題,求虐待 At least once a week, ask for problems and abuse 簡...

    pakolagij 評論0 收藏0
  • 用 PHP 的方式實現(xiàn)的各類算法合集

    摘要:數(shù)據(jù)項是數(shù)據(jù)的不可分割的最小單位。數(shù)據(jù)項是對客觀事物某一方面特性的數(shù)據(jù)描述。數(shù)據(jù)對象是性質相同的數(shù)據(jù)元素的集合,是數(shù)據(jù)的一個子集。數(shù)據(jù)的邏輯結構數(shù)據(jù)元素之間的相互關系稱為邏輯結構。 項目地址 https://github.com/m9rco/algo... 每周最少一更,求出題,求虐待 At least once a week, ask for problems and abuse 簡...

    leonardofed 評論0 收藏0

發(fā)表評論

0條評論

felix0913

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<