线性排序之:基数排序

    基数排序, radix sorting, 也叫bin sort, bucker sort, 基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。

基数排序法算法分析

基数排序的方式可以采用LSD(Leastsgnificant digital)或MSD(Most sgnificant digital),LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。

以LSD为例,假设原来有一串数值如下所示:

73, 22, 93, 43, 55, 14, 28, 65, 39, 81

首先根据个位数的数值,在走访数值时将它们分配至编号0到9的桶子中:

0 1 2 3 4 5 6 7 8 9
  81 22 73 14 55     28 39
      93   65        
      43            

接下来将这些桶子中的数值重新串接起来,成为以下的数列:

81, 22, 73, 93, 43, 14, 55, 65, 28, 39

接着再进行一次分配,这次是根据十位数来分配:

0 1 2 3 4 5 6 7 8 9
  14 22 39 43 55 65 73 81 93
    28              

接下来将这些桶子中的数值重新串接起来,成为以下的数列:

14, 22, 28, 39, 43, 55, 65, 73, 81, 93

这时候整个数列已经排序完毕;如果排序的对象有三位数以上,则持续进行以上的动作直至最高位数为止。

LSD的基数排序适用于位数小的数列,如果位数多的话,使用MSD的效率会比较好,MSD的方式恰与LSD相反,是由高位数为基底开始进行分配,其他的演 算方式则都相同。

 

索引的计算index =( original[j] %10^i)  /  10^(i-1)  // i=1代表各位数, i =2 代表百位数, 依次类推。。。

1. 使用C++实现LSD

#include <iostream> 
#include <vector>
#include <cmath>
using namespace std;    
    
const int len = 100+2;
const int highpos = 4;
class RadixSort  //计数排序类      
{    
public:    
    RadixSort();    
    ~RadixSort();    
    void sort();     
    friend ostream& operator<<(ostream& out,const RadixSort& countsort);    
private:    
    int *original;    
    int length;
	int pos;
};    
    
RadixSort::RadixSort():length(len),pos(highpos)    
{    
   original = new int[length];    
   for (int i=0; i<length-2; i++)    
   {    
       original[i] = rand()%1000; //random generated numbers in 0-1000 
   }  
   original[length-2] = 566;
   original[length-1] =566;
}    
    
RadixSort::~RadixSort()    
{    
    delete[] original;    
    original = NULL;    
}    
    
ostream& operator<<(ostream& out,const RadixSort& countsort)    
{    
  for (int i=0; i<countsort.length; i++)    
  {    
    cout<<countsort.original[i]<<" ";    
  }    
  cout<<endl;    
  return out;    
}  
  
void RadixSort::sort()    
{  
	typedef vector<int> singlebucket; //单个的桶结构为vector,可以保证相同index时候的稳定性, 也能够让长度可以扩展
	singlebucket Bucket[10];
	for(int i =1; i<pos; i++)
	{
		//clear the vector
		for(int i = 0; i <10; i++)
		{
			Bucket[i].clear(); //caution, should clear it here, not the downside, it will get wrong answer
		}
		//step1: input numbers to single bucket according to the index
		for(int j = 0; j < length; j++)
		{
			int index =( original[j] % (int)pow(10,(double)i))/(int)(pow(10,(double)(i-1))); 
			//Bucket[index].clear();
			Bucket[index].push_back(original[j]);
		}
		//step 2: take it out of bucket
		int posz = 0;
		for(int k = 0; k < 10; k++)
		{
			vector<int>::iterator ite = Bucket[k].begin();
			while(ite != Bucket[k].end())
			{
				original[posz++] = *ite;
				ite++;
			}
		}
	}
}    
int main()    
{    
    RadixSort *pcountsort = new RadixSort();    
    cout<<"排序前:"<<endl;    
    cout<<*pcountsort;    
      
    pcountsort->sort();      
    
    cout<<"排序后:"<<endl;    
    cout<<*pcountsort; 
	int x = 10^2;
	cout<<x<<endl;
    system("pause");    
    return 0;    
} 

注意: 上面的程序如果只是将

if(int i =1; i <pos; i++) 转变为 if(int i = pos-1; i>0; 1--) 是只能在所有变量位数相同才能得到正确结果, 否则是不可以的。

如果是我要实现MSD, 有种办法是使用循环递归, 从9到0, 然后依次迭代, 或者在第一次的各个bucket中采取其他的排序方法, 进行混合排序。

你可能感兴趣的:(C++,源代码,sort,排序算法,digital)