時空複雜度:
氣泡排序:時間o(n^2),額外空間o(1)
插入排序:時間o(n^2),額外空間o(1)
選擇排序:時間o(n^2),額外空間o(1)
基數排序:時間o(k*n)(k=logn_max),額外空間o(n)(臨時儲存)+o(b)(記數,b為基的大小)
記數排序:時間o(n+k),額外空間o(k)
希爾排序:時間o(n*logn^2),額外空間o(1)
快速排序:時間o(n*log(n)),額外空間o(logn)(遞迴棧)
歸併排序:時間o(n*log(n)),額外空間o(n)(臨時陣列)+o(logn)(遞迴棧)
堆排序: 時間o(n*log(n))
使快速排序退化的例子:
n, n-1, n-2, n-3.......3,2,1,快速排序具有o(n^2)的複雜度。
優化方法:隨機選擇劃分元素,而不是固定選擇最左面的元素。
對歸併來說,乙個很不理想的例子:
1,2,3,…… , n
對有序序列還是需要o(nlogn)的時間複雜度。
優化方法:找到序列的連續自增段,把這樣的自增段進行合併。
穩定排序和不穩定排序
穩定的排序演算法:氣泡排序、插入排序、基數排序、記數排序、歸併排序
非穩定排序演算法:希爾排序、選擇排序、快速排序、堆排序
實際上穩定排序可以實現成非穩定的,看具體的實現過程。有些同學誤以為自己寫了乙個氣泡排序就是穩定的,注意比較的時候是">=" 還是">"。
內部排序與外部排序
內部排序:內部排序是指待排序列完全存放在記憶體中所進行的排序過程,適合不太大的元素序列。
外部排序:外部排序指的是大檔案的排序,即待排序的記錄儲存在外儲存器上,待排序的檔案無法一次裝入記憶體,需要在記憶體和外部儲存器之間進行多次資料交換,以達到排序整個檔案的目的。最常用的外部排序是多路歸併排序。對於外部排序,影響速度的最主要因素為訪問磁碟的次數,所以設計外部排序演算法時,盡可能減少訪問磁碟的次數。
對於外部排序多路歸併演算法的時間複雜度進行簡要分析。
設有n個數,分成k段,之後利用m路歸併 。
t1 = n*log(n/k) 每段分別排序 n*log(n/k)。
t2 = n*logk 每趟對n個數合併(每個數每趟只操作一次),一共logk趟,
t3 = n * (t_read + t_write) * logk 從檔案中讀取和寫入數字花費的時間,
設每讀取乙個數的耗時為t_read,每次寫乙個數耗時為t_write,
t(n) = t1 + t2+t3 = n*log(n/k) + n*logk + n*(t_read+t_write)*logk ,其中logk是以m為底的。
所以,為了減少訪問磁碟的次數,必須增大基m,但是m並不是越大越好,如果越大,則在m個數中選擇最大值會越慢,所以一般都選m=9。
逆序數問題
對於序列 x1,x2,x3.......xn
若存在i>j,且滿足x[i] < x[j],則稱(x[i],x[j])構成乙個逆序對, 乙個序列所有的逆序對的數目叫做這個序列的逆序數。
例如序列 :5 4 3 2 1
逆序數為 1+2+3+4 = 10
利用歸併排序可以快速的求得乙個序列的逆序數。
尋找第k大數演算法
問題1:給出乙個序列,求這個序列第k大的數(離線)
比較通用的演算法:
(1) 利用快速排序的劃分。每次可以省去一部分的數進行查詢。
設下一次的查詢百分比為q<1,
時間 t(n) = n + t(n*q)
= n + n*q + t(n*q^2)
= n + n*q + n*q^2 + t(n*q^3)
= n(1 + q + q^2 + q^3 + ......)
= n(1*(1-q^k)/(1-q))
當q=1/2時, t(n) = 2n = o(n)。
這種方法最壞情況下的時間複雜度是o(n^2)。
那麼有沒有能夠保證最壞時間複雜度是o(n)的演算法嗎?有
(2) 最壞時間下是o(n)複雜度的演算法
或參見《演算法導論》 p190-p191
針對普通的劃分和隨機化劃分的缺點,對選擇劃分數進行改進:選擇中位數的中位數進行劃分。
假設函式find(a, k, n)返回的是a陣列中第k大的元素,新的查詢演算法如下:
1:將輸入陣列的n個元素劃分為n/5組,每組5個元素,至多有乙個組的元素數目小於5。
2:尋找n/5個組的每個組的中位數。對每個組的5個元素利用插入排序,之後選擇中位數。
3: 對第2步找到的n/5個中位數遞迴呼叫find函式,找出其中位數x。
4:利用中位數x對輸入陣列進行劃分。並得出x的排位。
5:如果第四步得到的x的排位為k,則返回x。如果x的排位大於k,則在低區進行遞迴查詢,否則在高區進行查詢。
因為x是中位數,除去x本身所在的組和那個元素數目小於5的組不算,大於x的元素數目至少為3*(1/2)*(n/5 - 2) = 3*n/10 - 6。
同理小於x的元素數目至少為3*n/10 - 6。那麼第4步最多有n-(3*n/10-6) = 7*n/10+6個元素參加下次的遞迴查詢。
設find(a, k, n)花費時間為t(n)。
則t(n) = t1 + t2 + t3 + t4 + t5。
t1 = o(n) (分成n/5組)
t2 = o(n) (每組進行選擇可以看做o(1)時間花費)
t3 = t(n/5) (對n/5個中位數遞迴選擇)
t4 = o(n) (根據x進行劃分)
t5 = t(7*n/10 + 6) (下一次遞迴選擇)
t(n) = t(n/5) + t(7*n/10 + 6) + o(n)
最後可推算出t(n)=o(n),但是個人認為常數比較大。
k非常小時情況下的選擇第k大元素演算法:
利用冒泡或者選擇排序,時間複雜度o(k*n)。
基本排序排序演算法
時空複雜度 氣泡排序 時間o n 2 額外空間o 1 插入排序 時間o n 2 額外空間o 1 選擇排序 時間o n 2 額外空間o 1 基數排序 時間o k n k logn max 額外空間o n 臨時儲存 o b 記數,b為基的大小 記數排序 時間o n k 額外空間o k 希爾排序 時間o ...
排序演算法 基本選擇排序
選擇排序是一種簡單直觀的排序演算法,基本思想是每一次從待排序的資料元素中選出最小 或最大 的乙個元素,存放在序列的起始位置,直到全部待排序的資料元素排完。n個元素的數列,需要n 1趟直接排序。拿第1個元素,依次與後面的其他元素逐個比較,找出最小 最大 的元素,放到下標為0的位置。經過第1步,數列的第...
基本排序演算法 選擇排序
排序方式 選擇排序 表現最穩定的排序演算法之一 這個穩定不是指演算法層面上的穩定 因為無論什麼資料進去都是o n 的時間複雜度 所以用到它的時候,資料規模越小越好。唯一的好處可能就是不占用額外的記憶體空間了吧。理論上講,選擇排序可能也是平時排序一般人想到的最多的排序方法了吧。原理首先從原始陣列中找到...