對k個序列按長度由大到小排序 排序演算法(8)

2021-10-18 19:46:13 字數 2924 閱讀 5659

本片文章做為排序演算法系列的擴充套件介紹兩個排序演算法,並行排序和量子排序,不要被名字唬住,讓我們來慢慢來探索吧。

雙調排序(bitonic sort)由ken batcher在2023年建立的,是基於比較的並行排序演算法,其主要思想是將隨機序列轉換為雙調序列,即序列單調遞增,單調遞減(移位雙調序列也是雙調序列),然後對雙調序列進行排序的過程,演算法主要分為兩部分,第一步是將無序的序列轉換為雙調序列;第二部分將序列等倍劃分為多個小序列比較排序直到整個序列有序。下面對其進行詳細介紹。

賽前預熱

雙調序列

雙調序列(bitonic sequence) 是指由乙個非嚴格增序列x 和 非嚴格減序列y構成的序列,任意兩個數,都是雙調序列。(非嚴格指的是可以出現重複元素,或者nan不參與排序)

定義:乙個序列 a1,a2, …,an 是雙調序列(bitonic sequence),如果: (1)存在乙個 ak(1 ≤ k ≤ n),使得 a1 ≥ … ≥ ak ≤ … ≤ an 成立;或者 (2)序列能夠迴圈移位滿足條件(1)條件(2)非常重要,因為好多序列表面不是,其實是雙調的

##batcher定理 將任意乙個長為2n的雙調序列a分為等長的兩半x和y,將x中的元素與y中的元素一一按原序比較,即a[i]與a[i+n] (i < n)比較,將較大者放入max序列,較小者放入min序列。則得到的max和min序列仍然是雙調序列,並且max序列中的任意乙個元素不小於min序列中的任意乙個元素。

比賽開始

bitonic merge

bitonic merge, 實際上也是分治divide and conquer的思路。 其過程是bottom up——將兩個相鄰的,單調性相反的單調序列看作乙個雙調序列, 每次將這兩個相鄰的,單調性相反的單調序列merge生成乙個新的雙調序列, 然後排序(雙調排序)。 這樣只要每次兩個相鄰長度為n的序列的單調性相反, 就可以通過連線得到乙個長度為2n的雙調序列,然後對這個2n的序列進行一次雙調排序變成有序,然後在把兩個相鄰的2n序列合併(在排序的時候第乙個公升序,第二個降序)。 n開始為1, 每次翻倍,直到等於陣列長度, 最後就只需要再一遍單方向(單調性)排序了。

以16個元素的array為例,

相鄰兩個元素合併形成8個單調性相反的單調序列,

兩兩序列合併,形成4個雙調序列,分別按相反單調性排序

4個長度為4的相反單調性單調序列,相鄰兩個合併,生成兩個長度為8的雙調序列,分別排序

2個長度為8的相反單調性單調序列,相鄰兩個合併,生成1個長度為16的雙調序列,排序

詳細bitonic merge圖(本圖只畫到生成乙個16長的雙調序列,最後排序沒有畫出):

最後再放乙個8個元素排序的示意圖:

bitonic sort雙調排序

上一步中我們生成乙個雙調序列,則我們根據batcher定理,將該序列劃分成2個雙調序列,然後繼續對每個雙調序列遞迴劃分,得到更短的雙調序列,直到得到的子串行長度為1為止。這時的輸出序列按單調遞增順序排列。

見下圖:公升序排序,具體方法是,把乙個序列(1…n)對半分,假設n=2^k,然後1和n/2+1比較,小的放上,接下來2和n/2+2比較,小的放上,以此類推;然後看成兩個(n/2)長度的序列,因為他們都是雙調序列,所以可以重複上面的過程;總共重複k輪,即最後一輪已經是長度是2的序列比較了,就可得到最終的排序結果。

這樣的雙調排序演算法只能應付長度為2的冪的陣列。那如何轉化為能針對任意長度的陣列呢?乙個直觀的方法就是使用padding。即使用乙個定義的最大或者最小者來填充陣列,讓陣列的大小填充到2的冪長度,再進行排序。最後過濾掉那些最大(最小)值即可。這種方式會使用到額外的空間,而且有時候padding的空間比較大(如陣列長度為1025個元素,則需要填充到2048個,浪費了大量空間)。但是這種方法比較容易轉化為針對gpu的並行演算法。所以一般來說,平行計算中常使用雙調排序來對一些較小的陣列進行排序[3]。 如果要考慮不用padding,用更複雜的處理方法,參考[4] n!=2^k的雙調排序網路。

最後附上雙調排序的c實現**:

bogo排序,又叫猴子排序 ,是個「既不實用又原始」的排序演算法,其原理等同將一堆卡片拋起,落在桌上後檢查卡片是否已整齊排列好,若非就再拋一次。其名字源自 quantum bogodynamics,又稱 bozo sort、blort sort 或猴子排序,在最壞的情況下所需時間是無限的。

偽**實現:

這麼乙個看似搞笑的演算法為什麼會讓人們關注,並且還在這裡介紹呢?原因就是其存在理論支撐啊,依照量子理論的平行宇宙解釋,使用量子隨機性隨機地重新排列元素,不同的可能性將在不同的宇宙中展開,總有一種可能猴子得到了正確的順序,量子計算機找到了這個宇宙後,就開始毀滅其他排序不成功的宇宙,剩下乙個觀察者可以看到的正確順序的宇宙。其實現複雜度聲稱可以用o(n)實現bogo排序。量子計算機已經出現了,現在就剩下平行理論的的證明了,這一步達到了,就是這個演算法的巔峰時刻。

傳統排序演算法大家都知道的七七八八了,稍加複習基本上都不成問題,但是並行排序我相信很多人涉及的還是比較少的,畢竟在實際生產活動中,手寫乙個並行的排序演算法還是不多見的(達到這個級別的人目前還沒見過),最後乙個演算法可以擴充套件知識面(最大的用處就是吹牛的時候),哈哈,排序演算法系列的文章也基本上暫時結束了,為什麼是暫時,因為學海無涯啊,攢幾個nb的演算法我們這個系列也是會繼續延續的。

對乙個整數按位反轉

記得在以前也是寫過乙個按位反轉 reversing bits 的文章,都是自己的,寫的傻乎乎的。這次重新對它進行了書寫。再加上由於看了 henry s.warren 的 hacker s delight 一書中的有關 reversing bits 的相關介紹,所以寫了這篇筆記。unsigned in...

按字串長度切割字串(支援漢字佔2個長度)

按指定長度切割字串 漢字算2個字元長度 輸入字串 按指定長度切割換行 輸出字串 中英混合行可能是newlinlength 1個長度 public string stringsplit string input,int newlinlength 5 return sbresult.tostring 按...

LeetCode 23 合併 K個排序序列

合併 k 個排序鍊錶,返回合併後的排序鍊錶。請分析和描述演算法的複雜度。示例 輸入 1 4 5,1 3 4,2 6 輸出 1 1 2 3 4 4 5 6 解題思路 採用分治的思想,將 k 個鍊錶的合併問題轉換成,合併 2 個有序鍊錶的問題 typedef struct listnode list 定...