1. 程式人生 > >虛擬碼演算法之快速排序(分治排序)

虛擬碼演算法之快速排序(分治排序)

開始的地方應該有個標題

我目前認為:名字不應該僅僅是一個符號,如果可以的話,應該能達到某種程度的“顧名思義”。
所以,我認為,應該叫做分治排序
所以,你應該先知道什麼是“分治”。顧名思義,分治就是“分而治之”。為了減少知識的耦合,這裡並不詳細介紹“分治”。

假如有這樣一列數:7,4,8,6,5,9,1,2,3,10。

第一步

我們先隨便挑一個數,比如“8”。
把比8小的放在8的左邊,把比8大的放在8的右邊。
先不要考慮用程式碼實現這個過程,因為步步為營將會寸步難行,你應該先熟悉整個流程,細節的地方下面會有介紹。所以,不要多想,繼續往下看。
這樣,以8為界,我們得到了兩列數。
結果有可能是這樣的(當然,這是我隨便分的,只要結果是比8小的在左,比8大的在右就好):
7,4,6,5,1,2,3,8

,9,10
我們給第一步這個流程起個名字,叫“造分水嶺”。

第二步

我們分別對第一步裡得到的兩列數(8的左邊和右邊)進行造分水嶺的流程。
也就是說:
對於7,4,6,5,1,2,3
我們再次隨機找一個喜歡的數,然後把比它小的放在它的左邊,比它大的放在它的右邊。比如,這次我們選中了6。
那麼結果可能是這樣的:4,5,1,2,3,6,7。
然後對於9,10這列數,我們也進行同樣的操作。

最後

其實到這裡,你可能已經知道分治排序的核心思想了,很簡單的東西。簡單來說,就是先對整個數列造分水嶺,然後對分水嶺兩邊的子數列造分水嶺,然後對得到的新數列繼續造分水嶺,直到得到的子數列中只有一個數。
這樣,排序這個任務也就完成了。其中的美妙之處,就只能自己體會了。

如果有人認為分治排序對新手來說是個“難題”

如果有人認為分治排序對新手來說是個難題,那麼可能難點就是“如何把比8小的放在8的左邊,把比8大的放在8的右邊”。
還用之前的那列數做示例:7,4,8,6,5,9,1,2,3,10

  • 先從數列的右邊往左找,直到找到一個比8小的數(本例中是3);
  • 8與3換位置;(結果A:7,4,3,6,5,9,1,2,8,10)
  • 再從數列的左邊往右找,直到找到一個比8大的數(本例中是9);
  • 9與8換位置;(結果B:7,4,3,6,5,8,1,2,9,10)
  • 再從數列的右邊往左找,直到找到一個比8小的數(由於結果A中,已經確定最右邊的10是比8大的,所以,這次從10左邊開始找,這次找到的是2)
  • 8與2換位置;(結果C:7,4,3,6,5,2,1,8,9,10)
  • 再從數列的左邊往右找,直到找到一個比8大的數(由於結果B中,已經確定最左邊的7,4,3,6,5是比8小的,所以,這次從5的右邊找,這次沒有找到,說明左邊的數已經全是比8小的了)
  • 這時發現8的右邊也全是比8大的了。

想象一下,這是一個怎樣的過程?
像有兩輛推土機,面對面開過來,推土機中間是這列數。
右邊的推土機往左開,直到遇到比8小的。
停下來,換位置。
左邊的推土機往右開,直到遇到比8大的。
停下來,換位置。
右邊的推土機從上次停下來的位置繼續往左開,直到……。……。
左邊的推土機從上次停下來的位置繼續往右開,直到……。……。

這就是分治排序