这种排序叫倍增排序,用于对正整数排序,负整数的话可以先都加上一个大的正数再用这种排序,它是基于寻址来排序的,不像快排是基于比较的,倍增排序的速度比快速排序快,是稳定的,不会退化到O(n^2),其时间复杂度为O(n+sqrt(m))(此处m指这些正整数的最大值,用dword类型时取2^32-1,n指待排序数的个数),空间复杂度也是一样,怎么样?是不是比O(n*Logn)快?它的原理和计数排序相似,但排序用的指标不同,它是用a[i]和sqrt(m)的余数、商作为指标,为了加快运行速度,用位运算计算商和余数。
一下是pascal源代码:
const
max=65535;//这边的max就相当于sqrt(m),max一定要(11....11)形式的二进制数,这样才可以用and来求余,提高速度。
var
i,n:longint;
a,b:array[1..1000000]of longint;
m,d:array[0..max+1]of longint;
begin
readln(n);
for i:=1 to n do
begin
read(a[ i]);
inc(m[1+a[ i] and max]);//此时的m表示余数a[ i] mod (max+1)为的数有几个,a[ i] and max=a[ i] mod (max+1)
inc(d[1+a[ i] shr 16]);//此时的d表示商为a[ i] div (max+1)的数有几个,a[ i] shr 16=a[ i] div (max+1)
end;
for i:=1 to max+1 do
begin
inc(m[ i],m[i-1]);//此时的m表示余数小于i(因为前面有加1,所以这里是小于)的数字的个数
inc(d[ i],d[i-1]);//此时的d表示商小于i(因为前面有加1,所以这里是小于)的数字的个数
end;
for i:=1 to n do//这边是按照余数排序
begin
inc(m[a[ i] and max]);//设t=a[ i]and max,这里表示余数为t的数应该放在的地址,因为前面累加之后,m[ t]已经表示余数小于t的数字有多少个,所以当有数字的余数为t时,应从t+1个位置开始放置在b数组,inc(m[ t])表示放置第几个余数为t的数字的地址。
b[m[a[ i] and max]]:=a[ i];
end;
for i:=1 to n do//这边基于已经按照余数排好序的数据再按照商排序
begin
inc(d[b[ i] shr 16]);//设t=a[ i]shr 16,这里表示商为t的数应该放在的地址,因为前面累加之后,d[t]已经表示商小于t的数字有多少个,所以当有数字的商为t时,应从t+1个位置开始放置在a数组,inc(m[ t])表示放置第几个商为t的数字的地址。
a[d[b[ i] shr 16]]:=b[ i];
end;
for i:=1 to n-1 do write(a[ i],' ');
write(a[n]);
end.
200字以内,仅用于支线交流,主线讨论请采用回复功能。