乙個線性時間下的原地置換排序演算法

2021-05-31 23:32:51 字數 2542 閱讀 7481

乙個線性時間下的原地置換排序演算法

現有的線性時間排序(時間複雜度為ο(n)演算法,比如計數排序,基數排序,桶排序等,雖然在時間複雜度上都能保持線性,但不能進行原地置換排序,需要額外的輔助空間.乙個演算法能否同時做到時間複雜度為ο(n),空間複雜度為ω(1)呢?

我們知道,在現有的常規線性演算法(計數排序,桶排序,基數排序等)當中,計數排序和桶排序因為不是原地置換排序,因此都需要額外的輔助空間來完成排序,因此無法達到上述目的,而基數演算法本身是乙個復合演算法,如果能保證其位排序的演算法能做到空間複雜度為ω(1)和時間複雜度ο(n),那顯然可以達到上述要求的演算法目標.對於基數排序中的位排序要求必須具有穩定性.既要滿足線性時間,常量空間,並且穩定的演算法,在現有常用演算法中還沒有這種演算法可以達到這種要求。

我們選基數排序作為實現這個演算法目標的基本演算法,由於我們進行的是整數排序,基數排序的位就是整數二進位制表示裡的位,而對於整數的二進位制形式,每位上的數就只有0和1(這是個很有利的因素),而對0和1序列排序做到線性時間,只需要利用0作為基元,做一次快排劃分即可,快排劃分的演算法時間複雜度是ο(n),而且也是原地置換排序,空間上的要求可以滿足(ω(1)),但問題在於對於基數排序,要求其位排序必須是穩定排序,而快排劃分顯然不是穩定的。但如果我們能找到一種方法將這種不穩定帶來的影響消除,使得其不影響最終結果,問題就解決了。那麼而怎樣讓快排劃分不影響最終結果呢?

我們知道基數排序有兩種基本的形式,一種是從低位到高位進行排序,一種是從高位到低位進行,經過分析發現,如果採用從高位到低位的方式進行,是可以讓快排劃分不影響到最終結果的,我們考慮一般情況,設b(k),b(k-1)….,b(1)表示乙個基數排序所有的位(對於32位整數k=32),對第i位進行排序,而前m位(m=k-i-1)位已經排好序b(k)…b(i+1),在進行i位排序時,如果我們的快排劃分只針對前m位相同的情況進行,則快排劃分的結果顯然不會影響最終結果.這樣對於第i位上的一次快排,就可以轉換成若干個小區間的快排劃分(用前m位數進行劃分,前m位相同的為乙個區間),而且由於前m位已經排好序,那麼顯然前m位相同的都必然緊挨在一起,這種情況下雖然一次快排劃分變成了p次快排劃分(p下面是具體的c#語言下的演算法實現(為了減少交換次數,這裡位排序不是嚴格按照快排劃分進行,而是針對0和1的特點,用乙個指標i指向序列第1個1,遍歷指標在前,遇到0就與i交換,i隨後右移一位,這可以大大減少交換次數):

private void bitsortanddelrepeatorsa(int a)

//獲取陣列長度

int then = a.length;

//從高位到低位開始排序,這裡從31位開始,32位是符號位不考慮,

//或者單獨考慮。

for (int i = 31; i >= 1; i--)

//當前排序之前的值,只有該值相同才進行快排分組,如果不相同,

//則重新開始另外一次快排

//這很關鍵,否則快排的不穩定就會影響最後結果.

int theprvcb = a[0] >>(i)  ;

//快排開始位置,會變化

int thes = 0;

//快排插入點

int thei = thes-1;

//2進製基數,用於測試某一位是否為0

int thebase = 1 << (i-1);

//位基元始終為0,

int theaxbit = 0;

//分段快排,但總體上時間複雜度與快排分組一樣.

for (int j = 0; j < then; j++)

//獲取當前陣列值的前面已拍過序的位數值。

int thetmpprvcb = a[j]>> (i);

//如果前面已排過的位不相同,則重新開始一次快排.

if (thetmpprvcb !=theprvcb)

thes = j;

thei = thes - 1;

theaxbit = 0;

theprvcb = thetmpprvcb;

j--;//重新開始排,回朔一位.

continue;

//如果前面的數相同,則尋找第1個1,thi指向其

//如果相同,則按快排處理

int theaj = (a[j] &(thebase)) > 0 ? 1 : 0;

//如果是重新開始排,則尋找第1個1,並人thei指向其.這可以

//減少交換,加快速度.

if (thei < thes)

if (theaj == 0)

continue;

thei = j;//continue保證j從thei+1開始.

continue;

//交換.

if (theaj <= theaxbit)

int thetmp = a[j];

a[j] = a[thei];

a[thei] = thetmp;

thei++;

時間複雜度雖然有32*n,但由於32是個常數,因此整個演算法的時間複雜度還是ο(n),空間複雜度方面,演算法中只是利用了有限的幾個交換變數(<20),因此空間複雜度為ω(1)。但演算法的穩定性方面,由於其位演算法是不穩定的,因此整個演算法也是不穩定的。

該演算法經過我大量測試,其複雜度符合演算法分析結果。

乙個線性時間下的原地置換排序演算法

乙個線性時間下的原地置換排序演算法 現有的線性時間排序 時間複雜度為 n 演算法,比如計數排序,基數排序,桶排序等,雖然在時間複雜度上都能保持線性,但不能進行原地置換排序,需要額外的輔助空間.乙個演算法能否同時做到時間複雜度為 n 空間複雜度為 1 呢?我們知道,在現有的常規線性演算法 計數排序,桶...

Keras實現只有乙個神經元的線性回歸演算法

執行緒回歸例項教程 人為的構造一組由y 0.5x 2加上一些雜訊而生成的資料 資料量為200個,其中160個作為train set,後40個作為test set import numpy as np import matplotlib.pyplot as plt from keras.models ...

乙個時間效率為O n 的排序演算法

題目 請實現乙個排序演算法,要求時間效率為o n 允許使用常量大小的輔助空間不得超過o n 首先回顧一下自己實現了的幾種常用的排序演算法 一 插入排序 1 include2 using namespace std 3void insert sort int a,int size 414 a i 1 ...