倍增排序

這種排序叫倍增排序,用於對正整數排序,負整數的話可以先都加上一個大的正數再用這種排序,它是基於尋址來排序的,不像快排是基於比較的,倍增排序的速度 比快速排序快,是穩定的,不會退化到O(n^2),其時間複雜度爲O(n+sqrt(m))(此處m指這些正整數的最大值,用dword類型時取 2^32-1,n指待排序數的個數),空間 複雜度也是一樣,怎麼樣?是不是比O(n*Logn)快?它的原理和計數排序相似,但排序用的指標不同,它是用a和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.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章