基数排序(RedixSort)
来源:互联网 发布:js indexof函数 编辑:程序博客网 时间:2024/06/02 01:46
一. 目的与说明
进行基数排序练习。基数排序是对整数的每一位进行稳定排序。多次排序后,数据呈现有序状态。注意必须是稳定排序。可以推广到浮点数。
二. 代码实现
定义进制常量
#define NUMBER_SYSTEM 10
定义获取数字位数与制定位的数字
//获取整数位数 int GetDigitWidth(int nNum){ int nWidth(0); do{ nNum = nNum /10; nWidth++; } while (nNum); return nWidth; } //获取数字的某位上的数字,该算法不高效,仅演示用 int GetBitDigit(int nNum,int nBit){ int nBase(1),nBitDigit; for (int i = 1; i < nBit; i++){ nBase = nBase * 10; } nBitDigit = (nNum / nBase) % 10; return nBitDigit; }
MSD实现,从高位排序到低位
//Most Sigificant Digit first RadixSort,最高位有效数字优先的基数排序 //数位排序采用计数排序 void MSDRadixSort(T testArray[], int nSize){ LogInfo<T> log = LogInfo<T>(); log.ShowState("原始数组为:"); log.ShowArray(testArray, nSize); //一次遍历获取最大值 T TMax = testArray[0]; for (int i = 0; i < nSize; i++){ if (testArray[i]>TMax){ TMax = testArray[i]; } } //获取最大位数 int nWidth = GetDigitWidth(TMax); MSDRadixSortSub(testArray, 0, nSize - 1, nWidth); log.ShowState("最终数组为:"); log.ShowArray(testArray, nSize); } //Most Sigificant Digit first RadixSort,最高位有效数字优先的基数排序 //数位排序采用计数排序 void MSDRadixSortSub(T testArray[], int nBegin,int nEnd,int nBit){ //初始化计数器 T Count[NUMBER_SYSTEM]; int i(0),j(0); for (i = 0; i < NUMBER_SYSTEM; i++) Count[i] = T(0); //分配桶 T* testOut = new T[nEnd - nBegin + 1]; //计数器 for (i = nBegin; i <= nEnd; i++) Count[GetBitDigit(testArray[i], nBit)]++; //位置计算 for (i = 1; i < NUMBER_SYSTEM; i++) Count[i] = Count[i]+Count[i-1]; //根据位置大小产生排序 for (i = nEnd; i >= nBegin; i--){ j = GetBitDigit(testArray[i],nBit); testOut[Count[j] - 1] = testArray[i]; Count[j]--; } //将排序后的元素放回原桶 for (i = nBegin; i <= nEnd; i++) testArray[i]=testOut[i-nBegin]; delete[] testOut; int nPosBegin, nPosEnd; if (nBit > 1){ for (i = 0; i < NUMBER_SYSTEM; i++){ nPosBegin = Count[i]; nPosEnd = Count[i + 1] - 1; //第i个位置有数据 if (nPosBegin < nPosEnd){ MSDRadixSortSub(testArray, nPosBegin, nPosEnd, nBit - 1); } } } }
LSD实现,从最低位排序到最高位
//Last Sigificant Digit first RadixSort,最低位有效数字优先的基数排序 //数位排序采用计数排序 void LSDRadixSort(T testArray[], int nSize){ LogInfo<T> log = LogInfo<T>(); log.ShowState("原始数组为:"); log.ShowArray(testArray, nSize); //一次遍历获取最大值 T TMax = testArray[0]; for (int i = 0; i < nSize; i++){ if (testArray[i]>TMax){ TMax = testArray[i]; } } //获取最大位数 int nWidth = GetDigitWidth(TMax); //从最低有效位开始进行计数排序 for (int i = 1; i <= nWidth;i++) LSDRadixSortSub(testArray, nSize, i); log.ShowState("最终数组为:"); log.ShowArray(testArray, nSize); } //Last Sigificant Digit first RadixSort,最低位有效数字优先的基数排序 //数位排序采用计数排序 void LSDRadixSortSub(T testArray[], int nSize, int nBit){ //初始化计数器 T Count[NUMBER_SYSTEM]; int i(0), j(0); for (i = 0; i < NUMBER_SYSTEM; i++) Count[i] = T(0); //分配桶 T* testOut = new T[nSize]; //计数器 for (i = 0; i <nSize; i++) Count[GetBitDigit(testArray[i], nBit)]++; //位置计算 for (i = 1; i < NUMBER_SYSTEM; i++) Count[i] = Count[i] + Count[i - 1]; //根据位置大小产生排序 for (i = nSize-1; i >= 0; i--){ j = GetBitDigit(testArray[i], nBit); testOut[Count[j] - 1] = testArray[i]; Count[j]--; } //将排序后的元素放回原桶 for (i = 0; i <nSize; i++) testArray[i] = testOut[i]; delete[] testOut; }
测试代码
int main(){ using namespace Test; using namespace MyAlgorithm; using namespace std; LogInfo<int> log = LogInfo<int>(); Sort<int> sortTest = Sort<int>(); log.ShowState("测试LSD基数排序"); log.ShowLine(); log.ShowState("测试正序数组========================"); log.ShowLine(); TestDataCreator<int, N_MAX> testArray = TestDataCreator<int, N_MAX>(PositiveArray); sortTest.LSDRadixSort(testArray.GetArray(), testArray.GetSize()); log.ShowState("测试降序数组========================"); log.ShowLine(); testArray = TestDataCreator<int, N_MAX>(NegativeArray); sortTest.LSDRadixSort(testArray.GetArray(), testArray.GetSize()); log.ShowState("测试随机数组========================"); log.ShowLine(); testArray = TestDataCreator<int, N_MAX>(RandomArray); sortTest.LSDRadixSort(testArray.GetArray(), testArray.GetSize()); int nWait; cin >> nWait; return 0;}
结果输出
三. 遇到问题
1、MSD实现缓存数组没有减去下标nBegin,导致下标越界。产生古怪数据。
2、对LSD算法存在疑问
四. 经验总结
1、LSD实现,必须要求稳定排序,才能排序成功。
2、MSD实现的稳定性依赖于每位数字排序算法的稳定性。
3、时刻注意下标问题。
4、本例数位排序采用了计数排序。该算法稳定依赖于倒序定位。
5、基数排序依靠计数内排序的复杂度分析:算法稳定。空间复杂度O(N+K),时间复杂度O(d(N+K)).
五. 后续任务
进行桶排序练习。
六. 参考文献
1、算法导论
2、 八大排序算法 http://blog.csdn.net/abcbig/article/details/42774333
3、基数排序http://www.cnblogs.com/Braveliu/archive/2013/01/21/2870201.html
0 0
- 基数排序(RedixSort)
- 86 dataS redixSort mit
- 基数排序
- 基数排序
- 基数排序
- 基数排序
- 基数排序
- 基数排序
- 基数排序
- 基数排序
- 基数排序
- 基数排序
- 基数排序
- 基数排序
- 基数排序
- 基数排序
- 基数排序
- 基数排序
- 用OpenInventor实现的NeHe OpenGL教程-第十九课
- JDK动态代理实现原理
- 用OpenInventor实现的NeHe OpenGL教程-第二十课
- 用OpenInventor实现的NeHe OpenGL教程-第二十一课
- 用OpenInventor实现的NeHe OpenGL教程-第二十二课
- 基数排序(RedixSort)
- 用OpenInventor实现的NeHe OpenGL教程-第二十三课
- 用OpenInventor实现的NeHe OpenGL教程-第二十四课
- 用OpenInventor实现的NeHe OpenGL教程-第二十五课
- 用OpenInventor实现的NeHe OpenGL教程-第二十六课
- 用OpenInventor实现的NeHe OpenGL教程-第二十七课
- 2016CampDay7problemF.Frank Sinatra
- 用OpenInventor实现的NeHe OpenGL教程-第二十八课
- 用OpenInventor实现的NeHe OpenGL教程-第二十九课