io.open();//打开控制台


/*
 *-------------------------------------------------------
 * 基数排序
 **------------------------------------------------------
 */
 
/*
基数排序从低位到高位进行，使得最后一次计数排序完成后，数组有序。
其原理在于对于待排序的数据，整体权重未知的情况下，
先按权重小的因子排序，然后按权重大的因子排序。

例如比较时间，先按日排序，再按月排序，最后按年排序，仅需排序三次。
但是如果先排序高位就没这么简单了。

基数排序源于老式穿孔机，排序器每次只能看到一个列，
很多教科书上的基数排序都是对数值排序，数值的大小是已知的，与老式穿孔机不同。
将数值按位拆分再排序，是无聊并自找麻烦的事。

算法的目的是找到最佳解决问题的方案，而不是把简单的事搞的更复杂。

基数排序更适合用于对时间、字符串等这些整体权值未知的数据进行排序。
这时候基数排序的思想才能体现出来，例如字符串，如果从高位（第一位）往后排就很麻烦。
而反过来，先对影响力较小，排序排重因子较小的低位（最后一位）进行排序就非常简单了。
这时候基数排序的思想就能体现出来。

又或者所有的数值都是以字符串形式存储，就象穿孔机一样，每次只能对一列进行排序。
这时候基数排序也适用，例如：对{"193";"229";"233";"215"}进行排序

下面我们使用基数排序对字符串进行排序。
对每个位循环调用计数排序。


*/
 

//计数排序算法
radix_sort = function( array ,maxlen){
 
 	//AAuto在字符串索引越界时，会返回0，这使基数排序的实现更加简单。
	//我们首先找出最大的排序长度，然后对于不足此长度的字符串，尾部都假定以0补齐。
	//对于超出此长度的位在比较时忽略
	if(!maxlen){  
		maxlen =0;
		for(i=1;#array;1){
			
	  		maxlen = math.max(maxlen,#array[i] )
		}
	}
	//else{
		//最大排序长度也可以从参数中传过来，这样就不用遍历所有字符串了
	//}
	
	
	
	//从字符串的最后一位开始，到第一位
	for(pos=maxlen;1;-1){
		//按当前位的字节码计数排序
		var array_sorted ={};
		
		var count = {};
		for(i=0;256 ){
	  		count[i] = 0;
		}
		
		var bytecode;
		for(i=1;#array;1){
			//如果pos大于字符串长度，AAuto会返回0，这使基数排序的实现更容易
			bytecode = array[i][pos] ;
			count[ bytecode ] ++; //count[n] 包含等于n的个数 
		}
	 	
		//统计位置
		for(i=1;256;1){
			count[i] += count[i-1]; //count[i] 包含小于等于i的个数 
		}
	 	
		var n;
		for(i=#array;1;-1){
			n = array[i][pos] 
			array_sorted[ count[n] ] = array[i];
			count[n]--;//防止相同的元素n再次出现，将计数减一 
		}
	 	
		array = array_sorted;  
	 
	}	
	  
	
	return array
}


io.print("----------------")
io.print("基数排序( 线性时间排序 )")
io.print("----------------")

array ={"AAuto is quicker and better,just try it!";"AAuto Quicker";"193";"229";"233";"215";"Hello Word";"abc";"abcd";"xd";"adcd";"eddd";"ah";"ai";"aj";"ajkk"}; 

//排序
array = radix_sort(array  )

//输出结果
for(i=1;#array;1){
	io.print( array[i] )
}
 

execute("pause") //按任意键继续
io.close();//关闭控制台

