您的位置:首页 > 其它

基数排序

2010-07-07 20:41 120 查看
基数排序是非比较排序算法,算法的时间复杂度是O(n).相比于快速排序的O(nlgn),从表面上看具有不小的优势.但事实上可能有些出入,因为基数排序的n可能具有比较大的系数K.因此在具体的应用中,应首先对这个排序函数的效率进行评估.

基数排序的主要思路是,将所有待比较数值(注意,必须是正整数)统一为同样的数位长度,数位较短的数前面补零.然后,从最低位开始,依次进行一次稳定排序(我们常用上一篇blog介绍的计数排序算法,因为每个位可能的取值范围是固定的从0到9).这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列.

比如这样一个数列排序:34258576356,以下描述演示了具体的排序过程(红色字体表示正在排序的数位)

第一次排序(个位):

342

576

356

058

第二次排序(十位):

342

356

058

576

第三次排序(百位):

058

342

356

576

结果:58342356576

两个问题:

为什么要从低位开始向高位排序?

如果要从高位排序,那么次高位的排序会影响高位已经排好的大小关系.在数学中,数位越高,数位值对数的大小的影响就越大.从低位开始排序,就是对这种影响的排序.数位按照影响力从低到高的顺序排序,数位影响力相同则比较数位值.

为什么同一数位的排序子程序要使用稳定排序?

稳定排序的意思是指,待排序相同元素之间的相对前后关系,在各次排序中不会改变.比如实例中具有十位数字5的两个数字58和356,在十位排序之前356在58之前,在十位排序之后,356依然在58之前.

稳定排序能保证,上一次的排序成果被保留,十位数的排序过程能保留个位数的排序成果,百位数的排序过程能保留十位数的排序成果.

算法的C#实现(综合了计数排序算法作为数位内排序算法):

publicstaticint[]RadixSort(int[]ArrayToSort,intdigit)

{

//lowtohighdigit

for(intk=1;k<=digit;k++)

{

//temparraytostorethesortresultinsidedigit

int[]tmpArray=newint[ArrayToSort.Length];


//temparrayforcountingsort

int[]tmpCountingSortArray=newint[10]{0,0,0,0,0,0,0,0,0,0};


//CountingSort

for(inti=0;i<ArrayToSort.Length;i++)

{

//splitthespecifieddigitfromtheelement

inttmpSplitDigit=ArrayToSort[i]/(int)Math.Pow(10,k-1)-(ArrayToSort[i]/(int)Math.Pow(10,k))*10;

tmpCountingSortArray[tmpSplitDigit]+=1;

}


for(intm=1;m<10;m++)

{

tmpCountingSortArray[m]+=tmpCountingSortArray[m-1];

}


//outputthevaluetoresult

for(intn=ArrayToSort.Length-1;n>=0;n--)

{

inttmpSplitDigit=ArrayToSort
/(int)Math.Pow(10,k-1)-(ArrayToSort
/(int)Math.Pow(10,k))*10;

tmpArray[tmpCountingSortArray[tmpSplitDigit]-1]=ArrayToSort
;

tmpCountingSortArray[tmpSplitDigit]-=1;

}


//copythedigit-insidesortresulttosourcearray

for(intp=0;p<ArrayToSort.Length;p++)

{

ArrayToSort[p]=tmpArray[p];

}

}


returnArrayToSort;

}


这个算法的难度在于分离数位,将分离出的数位代表原元素的代表,用作计数排序.但是分离数位不能脱离原来的数字,计数排序的结果,还是要移动原元素.

注意计数排序的元素数值与位置的联系,引申到基数排序的从元素得到中间值然后与位置的联系.

测试程序如下:

staticvoidMain(string[]args)

{

int[]ary=newint[]{332,653,632,755,433,722,48};


int[]res=RadixSort(ary,3);


foreach(intvrinres)

{

Console.Write(vr.ToString()+"");

}


Console.ReadLine();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: