前言如果你準備看這篇文章,我就當你是懂快速排序演算法原理的。下面是我在2018年10月3日想到的基於二進位制位運算對正整數進行的一種快速排序演算法,目前的程式碼只能對正整數進行有效的排序,當然,稍微修改一下就可以支援負數的排序了。後面會給出我用Julia語言實現的沒有經過最佳化的程式碼和一些測試結果。如果您對此能有什麼改進或者能幫嗎最佳化一下程式碼,請告知我一下,我會非常感謝您。下面是此演算法的思想和原理。2是一個神奇的數字,可以用來做很多東西,二叉樹,二分搜尋,快速冪演算法以及很多分治演算法都是在2這個神奇的數字的幫助才能達到他們的優雅和高效率。利用二進位制,我們也可以進行快速排序。如果要對一列數字進行排序,你會怎樣去做呢?學過快速排序的同學應該會立即想到快速排序。先選一個數字,然後從兩邊開始,分別把小於它的數字交換到它的左邊,把大於它的數字交換到它右邊,完成這一過程,其右邊的數字全體大於等於它,左邊的數字全部小於等於它。然後分別對其左邊和右邊遞迴地運用此方法(快速排序)進行排序,當排序的長度小於2時,遞迴過程完成了,這一列數字也就變成有序的了。這種最基本的快排演算法是不是也散發著二分的思想?如果它再二一點會怎樣?那就是我下面想要談論的基於二進位制的快速排序演算法了。哈哈,我給它加入了二進位制。其實除開二進位制的位運算,這個演算法跟快速排序演算法基本上是一樣的,所以我暫且稱之為BQuickSort(Binary or Bit)。演算法的基本思想對每一個二進位制位,把該位是1的數字劃分到右邊,是0的劃分到左邊。高位優先,透過交換來進行。實現在演算法的實現上我採用了按位與運算,先用的時間複雜度求出其中最大的數字,然後對最大的數字進行一次簡單的flp2運算(把其二進位制最高位之外的bit全部置0,這裡的最高位並非64或32等,而是左邊第一個不為0的bit),獲得一個為2的n次冪的整數變數,我們暫且把它命名為shift。每一次所做的就是用這個shift與一個要排序的區間段進行按位與運算運算,將右邊運算結果為0的數字同左邊運算結果不為0的數字進行交換,並返回交換之後的分割位置。然後遞迴地將同樣的演算法運用於分割位置的左邊和右邊,只需將shift右移一位即可。遞迴結束的條件是區間寬度小於1或者shift等於0。對於一次部分排序,我寫了兩個函式,一個像快速排序那樣從兩邊向中間行進,是不穩定的演算法,另一個只從左邊行進,應該是穩定的演算法。演示接下來我將演示對下列所示的整數序列進行的BQuickSort。 在這裡最大的數字是10(二進位制為1010),透過對10進行flp2運算,我們將獲得一個數字8(二進位制為1000)。將shift(這裡為8)同每一個數字進行按位與運算並把運算結果不為0的數字交換到右邊,最後我們返回一個整數索引10,它記錄了一次排序之後的分割線(分割線左邊的數字都小於8,同8進行按位與運算為0;右邊的數字都大於等於8,同8進行按位與運算不為0)。 鑑於分割線及其右邊的數字都大於左邊的數字,下面值演示對左邊的數字進行的排序,同樣的方法適用於右邊。將shift右移一位(結果為4),然後與分割線左邊的數字(前9個)進行與上面一樣的部分排序操作,我們將得到下面這張圖所示的序列。 再對前3個數字進行shift為2的部分排序,1將被交換到左邊,此時前3個數已經有序,但是遞迴其實尚未結束,下一次遞迴是shift為1的一次部分排序。繼續對第4~9個數字執行同樣的部分排序,最後我們將會得到前九個數字的有序排列。之後再對第10~12個數字進行同樣的部分排序,我們就會得到一個所有數字的有序排列。 演算法實現程式碼
一些測試結果[code][/code]
前言如果你準備看這篇文章,我就當你是懂快速排序演算法原理的。下面是我在2018年10月3日想到的基於二進位制位運算對正整數進行的一種快速排序演算法,目前的程式碼只能對正整數進行有效的排序,當然,稍微修改一下就可以支援負數的排序了。後面會給出我用Julia語言實現的沒有經過最佳化的程式碼和一些測試結果。如果您對此能有什麼改進或者能幫嗎最佳化一下程式碼,請告知我一下,我會非常感謝您。下面是此演算法的思想和原理。2是一個神奇的數字,可以用來做很多東西,二叉樹,二分搜尋,快速冪演算法以及很多分治演算法都是在2這個神奇的數字的幫助才能達到他們的優雅和高效率。利用二進位制,我們也可以進行快速排序。如果要對一列數字進行排序,你會怎樣去做呢?學過快速排序的同學應該會立即想到快速排序。先選一個數字,然後從兩邊開始,分別把小於它的數字交換到它的左邊,把大於它的數字交換到它右邊,完成這一過程,其右邊的數字全體大於等於它,左邊的數字全部小於等於它。然後分別對其左邊和右邊遞迴地運用此方法(快速排序)進行排序,當排序的長度小於2時,遞迴過程完成了,這一列數字也就變成有序的了。這種最基本的快排演算法是不是也散發著二分的思想?如果它再二一點會怎樣?那就是我下面想要談論的基於二進位制的快速排序演算法了。哈哈,我給它加入了二進位制。其實除開二進位制的位運算,這個演算法跟快速排序演算法基本上是一樣的,所以我暫且稱之為BQuickSort(Binary or Bit)。演算法的基本思想對每一個二進位制位,把該位是1的數字劃分到右邊,是0的劃分到左邊。高位優先,透過交換來進行。實現在演算法的實現上我採用了按位與運算,先用的時間複雜度求出其中最大的數字,然後對最大的數字進行一次簡單的flp2運算(把其二進位制最高位之外的bit全部置0,這裡的最高位並非64或32等,而是左邊第一個不為0的bit),獲得一個為2的n次冪的整數變數,我們暫且把它命名為shift。每一次所做的就是用這個shift與一個要排序的區間段進行按位與運算運算,將右邊運算結果為0的數字同左邊運算結果不為0的數字進行交換,並返回交換之後的分割位置。然後遞迴地將同樣的演算法運用於分割位置的左邊和右邊,只需將shift右移一位即可。遞迴結束的條件是區間寬度小於1或者shift等於0。對於一次部分排序,我寫了兩個函式,一個像快速排序那樣從兩邊向中間行進,是不穩定的演算法,另一個只從左邊行進,應該是穩定的演算法。演示接下來我將演示對下列所示的整數序列進行的BQuickSort。 在這裡最大的數字是10(二進位制為1010),透過對10進行flp2運算,我們將獲得一個數字8(二進位制為1000)。將shift(這裡為8)同每一個數字進行按位與運算並把運算結果不為0的數字交換到右邊,最後我們返回一個整數索引10,它記錄了一次排序之後的分割線(分割線左邊的數字都小於8,同8進行按位與運算為0;右邊的數字都大於等於8,同8進行按位與運算不為0)。 鑑於分割線及其右邊的數字都大於左邊的數字,下面值演示對左邊的數字進行的排序,同樣的方法適用於右邊。將shift右移一位(結果為4),然後與分割線左邊的數字(前9個)進行與上面一樣的部分排序操作,我們將得到下面這張圖所示的序列。 再對前3個數字進行shift為2的部分排序,1將被交換到左邊,此時前3個數已經有序,但是遞迴其實尚未結束,下一次遞迴是shift為1的一次部分排序。繼續對第4~9個數字執行同樣的部分排序,最後我們將會得到前九個數字的有序排列。之後再對第10~12個數字進行同樣的部分排序,我們就會得到一個所有數字的有序排列。 演算法實現程式碼
[/code][size=5]測試程式碼[/size][code]複製程式碼一些測試結果[code][/code]