线性时间的排序

  • 比较排序是无法突破O(nlg(n))的时间界限的,如若希望实现线性时间的排序,必须放弃比较的方式排序。
  • 下面要描述的计数排序,基数排序和桶排序,都不是比较排序,因此,O(nlg(n))对于他们来说不适用。
  • 计数排序:
    计数排序假设输入的序列的值是从0~k的,它不能原地的排序,因此需要另外一个输出区间;而且需要有一个辅助的区间,这个区间的大小与0~k的元素的个数相同。
    排序开始时,分配一个辅助区间,初始化为0;然后,将设置辅助区间各个位置上的值,使得第i个索引上的值,为数值为i的元素的个数。
    然后从1下标遍历这个辅助区间,令array[i] += array[i - 1],最终的结果是,对于索引为i的辅助区间的值,表示的是小于等于这个值的元素的个数。
    接下来就可以向输出区间上写入了。为了保持排序的稳定性,计数排序反向遍历输入区间,找到输入区间上的值x,就在辅助区间上找array[x](因为辅助区间的索引值和原始区间的实际值是对应相等的),找到的array[x]就是小于等于x的元素的个数,因此,只需要把x放到输出区间的array[x]-1这个位置上(减1是因为下标从0开始的),遍历完序列,排序也就完成了。
    算法中没有任何的序列内元素比较排序的迹象,而且循环都是最多为n次,时间复杂度为O(n)。
    void count_sort(const int *arr, int *dest, int upper, int first, int last)
    	{	//this algorithm use both the index and the value of an array to represent data.
    	int *host = new int[upper];
    	std::fill(host, host + upper, 0);
    	
    	//host[i]: count of values which are equal to i. eg: host[2] == 1, 
    	//means there are two '2'.
    	for(int i = 0; i < last - first; ++i)
    		++host[arr[i]];
    	//host[i]: count of values which are not greater than i. eg: host[2] = 3,
    	//means there are 3 numbers less or equal to 2.
    	for(int i = 1; i < upper; ++i)
    		host[i] += host[i - 1];
    	//place the number.
    	for(int i = last - 1; i >= first; --i)
    		dest[host[arr[i]] - 1] = arr[i], --host[arr[i]];
    	//clean up.
    	delete host;
    	host = NULL;
    	}
  • 基数排序
    void count_sort_spec_bit(const int *arr, int bit, int *dest, int first, int last, int scale = 10)// decimal base as default.
    {	//this algorithm use both the index and the value of an array to represent data.
    
    	int *const bitset = new int[last - first];
    
    	std::fill(bitset, bitset + last - first, 0);
    	for(int i = first; i != last; ++i)
    	{
    		int pow10 = 1;
    		int ite = bit;
    		for(; ite != 0; --ite, pow10 *= 10)
    			;
    
    		bitset[i] = arr[i] / pow10 % 10;
    	}
    
    	int *host = new int[scale];
    	std::fill(host, host + scale, 0);
    
    	//host[i]: count of values which are equal to i. eg: host[2] == 1, 
    	//means there are two '2'.
    	for(int i = 0; i < last - first; ++i)
    		++host[bitset[i]];
    	//host[i]: count of values which are not greater than i. eg: host[2] = 3,
    	//means there are 3 numbers less or equal to 2.
    	for(int i = 1; i < scale; ++i)
    		host[i] += host[i - 1];
    	//place the number.
    	for(int i = last - 1; i >= first; --i)
    		dest[host[bitset[i]] - 1] = arr[i], --host[bitset[i]];
    	//clean up.
    	delete []bitset;
    	delete []host;
    	host = NULL;
    }
    
    void RadixSort(const int *srcArray, int* destArray, int nCount)
    {
    	ASSERT(nCount > 0);
    	int *pTemp = new int[nCount];
    	std::copy(srcArray, srcArray + nCount, pTemp);
    	for(int nMax = *(std::max_element(pTemp, pTemp + nCount)), i = 0;
    		nMax != 0; nMax /= 10, ++i)
    	{
    		count_sort_spec_bit(pTemp, i, destArray, 0, nCount);
    		std::copy(destArray, destArray + nCount, pTemp);
    	}
    	delete []pTemp;
    	pTemp = NULL;
    }
    

     

posted @ 2012-09-03 22:05  Gallagher  阅读(131)  评论(0)    收藏  举报