1. 程式人生 > >不懂算法的程序員不是好工程師--選擇排序

不懂算法的程序員不是好工程師--選擇排序

list gui 次數 否則 https 微信公眾號 inf 時間復雜度 完全

“大菜”:時刻提醒自己,技術之路修遠兮,予以自勉。

技術分享圖片

算法主要衡量標準

  • 時間復雜度(運行時間)

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

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

技術分享圖片

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

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

  • 結果的正確性

    這個指標是菜菜自己加上的,我始終認為一個優秀的算法最終得到的結果必須是正確的。就算一個算法擁有非常優秀的時間和空間復雜度,但是結果不正確,又有什麽意義呢?

原理

在起始位置右側(或左側)找出最小的那個元素,然後和起始位置的元素交換

選擇排序是一個不穩定的排序算法

具體步驟如下:

  1. 在一個數據列表中找到最小的那個元素,將它和列表的第一個元素交換位置。
  2. 在第二個元素位置開始再次尋找最小的那個元素,然後和列表的第二個位置的元素交換。
  3. 在第三個元素位置開始再次尋找最小的那個元素,然後和列表的第三個位置的元素交換
  4. 如此反復,直到開始查找起始位置到達列表末尾。

    如果查找過程中最小的元素就是起止位置的元素,那麽它就和它自己交換。

++因為這種算法總是在不斷的選擇剩余元素中最小者,因此得名選擇排序++

技術分享圖片

復雜度

  • 時間復雜度
  1. 比較次數

    對於長度為N的列表,選擇排序需要大約n2 /2次比較.即:O(n2)平方級別。

  2. 交換次數

    對於長度為N的列表,選擇排序需要大約N次交換.即:O(N) 線性級別。

性能和特點

總體來說,選擇排序是一種比較簡單的排序算法,很容易理解也很好用代碼實現,當然他的特點也很明顯:

運行時間和數據初始狀態無關

為什麽這麽說呢?算法進行中為了查找最小的元素而遍歷列表並不能為下次遍歷帶來任何信息,這個特性在大部分情況下是缺點。如果一個數據列表初始狀態是有序的或者部分有序的,選擇排序仍然需要全部掃描一次和交換。因此和一個完全無序的列表排序所花的時間相差不大。

數據移動次數是最少的

每次交換只會改變兩個列表元素,因此長度為N的列表只會發生N次交換,交換次數和列表的長度是線性關系,其他算法都不具備這個特性。

適用場景

由於選擇排序的對比次數在平方級別,但是移動次數在線性級別,所以當N比較小的時候比較適用。

其他

  • 為什麽選擇排序不穩定呢?

    首先我們要明白算法穩定是什麽意思呢?

    在待排序的數據中,存在多個相同的數據,經過排序之後,他們的相對順序依舊保持不變,實際上就是說array[i]=array[j],i<j.就是array[i]在array[j]之前,那麽經過排序之後array[i]依舊在array[j]之前,那麽這個排序算法穩定,否則,這個排序算法不穩定。

根據以上定義很容易可以得出這樣的結論:

我們舉出一個實例,序列5 8 5 2 9, 這個在執行選擇排序的時候,第一遍,肯定會將array[0]=5,交換到2所在的位置,也就是 2 8 5 5 9,那麽很顯然,之後的排序我們就會發現,array[2]中的5會出現在原先的array[0]之前,所以選擇排序不是一個穩定的排序

實現案例

(c#)
        static void Main(string[] args)
        {
            List<int> data = new List<int>() ;
            for (int i = 0; i < 10; i++)
            {
                
                data.Add(new Random(Guid.NewGuid().GetHashCode()).Next(1, 100));
            }
            //打印原始數組值
            Console.WriteLine($"原始數據: {string.Join(",", data)}");
            int n = data.Count;
            for (int i = 0; i < n; i++)
            {
                int minIndex = i;
                //查找最小的元素的索引
                for (int j = i+1; j < n; j++)
                {
                    if (data[j] < data[minIndex])
                    {
                        minIndex = j;
                    }
                }
                //交換最小的元素和當前位置的元素,當然這裏可以加入一個最小元素是否是當前位置元素的判斷來較少交換次數
                int tempItem = data[i];
                data[i] = data[minIndex];
                data[minIndex] = tempItem;

            }
            //打印排序後的數組
            Console.WriteLine($"排序數據: {string.Join(",", data)}");
            Console.Read();
        }

運行結果:

原始數據:97,85,61,22,62,12,67,22,68,42

排序數據:12,22,22,42,61,62,67,68,85,97

Go

家裏沒環境,還得FQ,以後再補上吧,望見諒。


獨樂不如眾樂

老媽剛要收拾收拾衛生...老公就笑著說道:“媽,您大老遠過來,哪能讓你打掃家務...”然後老公就讓我帶我媽出去逛逛街,家務他全包了...就這樣,我被老媽拉了出去,我生氣的對老媽說道:“明明我都看到地毯底下的錢了,為什麽不讓我拿出來!”老媽淡定的說道:“要嘛,你現在回去把那錢拿出來翻臉!要嘛,現在就跟我逛街去!以後家務也不用做了!你選吧...

技術分享圖片

轉載請標明出處 ^ ~ ^ 。部分圖片來源於網絡,如有侵權請及時聯系。讓我們一起進步吧

一個不止於IT圈內容的微信公眾號,歡迎關註,交流更多的IT知識。

技術分享圖片

不懂算法的程序員不是好工程師--選擇排序