1. 程式人生 > >PCB 挺有意思的基數排序----C#代碼實現

PCB 挺有意思的基數排序----C#代碼實現

cap -s void 步驟 復雜 ddb com info 神奇

今天在頭條看一個很有意思的排序算法【基數排序】,以前所學習的排序算法都是基於數值對比的方式排序的,而這個算法挺有意思的非常獨特。但從網上看到的例子通常是對個位,十位處理,並轉為對應的桶索引的方式實現,這裏將此算法用C#實現,並以位運算的新方式實現。

一.代碼實現

        static void Main(string[] args)
        {
            //待排序數組
            List<int> arrlist = new List<int>() { 72, 11, 82, 32, 44, 13, 17, 95, 54, 28
, 79, 56 }; int Number = 3; //基數 網上教材都是基於個位,十位,百位進行運算,這裏通過位數計算 int NumCount = 1 << Number; //桶數 位數是3那麽桶數是8, 位數是4那麽桶數是16 List<List<int>> intList = new List<List<int>>(); //建立好桶 for (int i = 0; i < NumCount; i++) { intList.Add(
new List<int>()); } int LayerCount = 3; //位數劃分組數(計算方法:數組最大值為95,對應二進制為:1011111,基數為3的話,可以分為1,011,111; 組數為3) //算法實現-----算法復雜度(nxm) for (int k = 1; k <= LayerCount; k++) //最大整數最高位數劃分組數 { intList.ForEach(tt => tt.Clear());
foreach (var item in arrlist) { int index = item & ((1 << k * Number) - 1); //左移加與位運算 求桶索引 index = index >> (k - 1) * Number;//右移加與運算 求桶索引 intList[index].Add(item); } arrlist.Clear(); for (int i = 0; i < NumCount; i++) { for (int j = 0; j <intList[i].Count; j++) { arrlist.Add(intList[i][j]); } } } //輸出 arrlist.ForEach(tt=>Console.WriteLine(tt)); Console.ReadKey(); }

二.輸出排序結果:

技術分享圖片

三 .基數排序算法介紹:

基數排序的兩個關鍵要點:

(1)基:被排序的元素的“個位”“十位”“百位”,暫且叫“基”,栗子中“基”的個數是2(個位和十位);

畫外音:來自野史,大神可幫忙修正。

(2)桶:“基”的每一位,都有一個取值範圍,栗子中“基”的取值範圍是0-9共10種,所以需要10個桶(bucket),來存放被排序的元素;

基數排序的算法步驟為:

FOR (每一個基) {

//循環內,以某一個“基”為依據

第一步:遍歷數據集arr,將元素放入對應的桶bucket

第二步:遍歷桶bucket,將元素放回數據集arr

}

更具體的,對應到上面的栗子,“基”有個位和十位,所以,FOR循環會執行兩次。

【第一次:以“個位”為依據】

技術分享圖片

畫外音:上圖中標紅的部分,個位為“基”。

第一步:遍歷數據集arr,將元素放入對應的桶bucket;

技術分享圖片

操作完成之後,各個桶會變成上面這個樣子,即:個位數相同的元素,會在同一個桶裏。

第二步:遍歷桶bucket,將元素放回數據集arr;

畫外音:需要註意,先入桶的元素要先出桶。

技術分享圖片

操作完成之後,數據集會變成上面這個樣子,即:整體按照個位數排序了。

畫外音:個位數小的在前面,個位數大的在後面。

【第二次:以“十位”為依據】

技術分享圖片

畫外音:上圖中標紅的部分,十位為“基”。

第一步:依然遍歷數據集arr,將元素放入對應的桶bucket;

技術分享圖片

操作完成之後,各個桶會變成上面這個樣子,即:十位數相同的元素,會在同一個桶裏。

第二步:依然遍歷桶bucket,將元素放回數據集arr;

技術分享圖片

操作完成之後,數據集會變成上面這個樣子,即:整體按照十位數也排序了。

畫外音:十位數小的在前面,十位數大的在後面。

首次按照個位從小到大,第二次按照十位從小到大,即:排序結束。

神奇不神奇!!!

幾個小點:

(1)基的選取,可以先從個位開始,也可以先從十位開始,結果是一樣的;

(2)基數排序,是一種穩定的排序;

(3)時間復雜度,可以認為是線性的O(n);

PCB 挺有意思的基數排序----C#代碼實現