基数排序(RadixSort)

1 基数排序的特点是研究多个关键字key,且多个key之间有权重之分,

   或者可把单个key建模为含有多个key的排序

   而计数排序、桶排序始终只有个一个key,或者说围绕着一个比较规则

   Ex:比较年月日,先比较年份,如果相同,比较月份,如果还是相同,就比较日

2 根据首先选择有效位的不同,分为两种

   A. 先比较最高有效位,然后在比较次高位的有效位,以此类推进行比较MSD(Most Significant Dight)

     假如有189,321,312,167 需要考虑高有效位相同的情况与不同的情况

       最高位不同:直接分出大小,并且需要记住312与321 > 比189,167大 

       最高位相同:比较十位,并且根据上述记录只比较312与321之间的十位数,否则排序是不稳定的

   B. 先比较最低有效位,然后在比较次低位的有效位,以此类推进行比较LSD(Least Significant Dight)

       无需考虑MSD排序遇到的问题,直接对每个位数排序即可

       注意:每次排序只针对当前位数(辅助排序函数必须是基于稳定的)

3 可以使用基数排序对一些位数有限的十进制数排序(十进制整数每位固定大小0~9)

4 基数排序时间代价 O(d(n+k))(前提是辅助函数为计数排序的情况下)

   d为关键值key的位数的个数,每位排序执行计数排序需要O(n+k)

  1 #include <iostream>

  2 #include <crtdbg.h>

  3 #include <cstring>

  4 using namespace std;

  5 

  6 const int SIZE = 10;  //n的大小

  7 const int K = 1000;   //允许的最大整数

  8 enum numberBit

  9 {

 10     GeWei     = 1,

 11     ShiWei    = 10,

 12     BaiWei    = 100,

 13     QianWei   = 1000,

 14 };

 15 //获取当前位数,d表示位数

 16 int GetData(const int data, int d)

 17 {

 18     int tmp = 0;

 19     switch(d)

 20     {

 21     case GeWei:

 22         {

 23             tmp = data%10;

 24         }

 25         break;

 26     case ShiWei:

 27         {

 28             tmp = data%100;

 29             tmp = tmp/10;

 30         }

 31         break;

 32     case BaiWei:

 33         {

 34             tmp = data%1000;

 35             tmp = tmp/100;

 36         }

 37         break;

 38     case QianWei:

 39         {

 40             tmp = data/1000; //允许最大值为1000

 41         }

 42         break;

 43     default:

 44         {

 45             cout <<"wrong number, which big then k";

 46             return -1;

 47         }

 48         break;

 49     }

 50     return tmp;

 51 }

 52 //计数排序, d为当前位数

 53 void CountingSort(int array[], int size, int d)

 54 {

 55     //建立辅助数组pCount大小固定为10(0~9),用来存储统计的元素信息

 56     int *pCount = new int[10];   

 57     memset(pCount, 0, (10)*sizeof(pCount[0]));

 58      

 59     //建立辅助数组result存储结果

 60     int *result = new int[size]; 

 61     memset(result, 0, size*sizeof(result[0]));

 62 

 63     //数组p使用元素大小做为下标,统计array的每个元素的个数

 64     for(int i=0; i<10; ++i)

 65     {

 66         int position = GetData(array[i], d);  //获取元素的位置

 67         pCount[position] = pCount[position] + 1;

 68     }

 69 

 70     //数组p 记录每个元素x在数组array中 小于或等于x的个数 

 71     //比如个位数时:小于等于4 的为元素 为3个(0, 1000, 83) 

 72     for (int i=1; i<=9; ++i)

 73     {

 74         pCount[i] = pCount[i]+pCount[i-1];

 75     }

 76 

 77     //根据上述获取的信息,进行排序

 78     //比如个位数时:小于等于4的为元素为3个(0, 1000, 83),4的位置为第4个 

 79     for (int i=size-1; i>=0; --i)//此处为保证稳定性,从size-1 向 0 迭代 

 80     {

 81         int data = GetData(array[i], d);

 82         int position = pCount[data];      //获取数组array[i]的位置

 83         result[position-1] = array[i];    //放到正确的位置

 84         pCount[data]= pCount[data] - 1;   //更新该元素的个数

 85     }

 86     //把结果存储到最初的数组array

 87     for (int i=0; i<size; ++i)

 88     {

 89         array[i] = result[i];

 90     }

 91     delete [] pCount;

 92     delete [] result;

 93 }

 94 //基数排序,k为允许的最大整数

 95 void RadixSort(int array[], int size, int k)

 96 {

 97     //选择稳定排序即可,计数排序或者桶排序(桶排序具体实现请转到上一节)

 98     for (int i=1; i<=k; i=i*10) //i表示位数,从低有效位到高有效位 LSD 

 99     {

100         CountingSort(array, size, i);    //计数排序                                        

101     }

102 }

103 void main()

104 {

105     //检测是否有内存泄露 需要加头文件#include <crtdbg.h>

106     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

107 

108     int array[SIZE] = {328, 4, 456, 656, 0, 1000, 439, 725, 328, 83,};

109 

110     RadixSort(array, SIZE, K);

111 

112     for (int i=0; i<SIZE; ++i)

113     {

114         cout << array[i] << endl;

115     }

116 

117     system("pause");

118 }

 

(转载请注明作者和出处^_*  Seven++ http://www.cnblogs.com/sevenPP/  )

 

你可能感兴趣的:(sort)