排序演算法:是將一組資料,按照指定的順序進行排列的過程。
排序的分類:
1、內部排序:將需要處理的所有資料載入到記憶體儲存器中排序
2、外部排序:資料量過大,無法全部載入到記憶體中,需要借助外部儲存進行排序。
常見的排序演算法分類如下所示,外部排序先略過。
衡量乙個程式(演算法)執行時間的兩種方法
1、事後統計法
這種方法可行,但是有兩個問題,1)如果想要對設計的演算法進行執行效能評測,需要實際執行程式。2) 運算的所得的時間的統計量依賴於計算機的硬體、軟體等環境因素,這種方式需要在同等條件、同等狀態下執行,才能比較演算法的速度。
2、事前估算法:通過分析某個演算法的時間複雜度來判斷哪個演算法更好。
時間頻度
乙個演算法花費的時間與演算法中語句的執行次數成正比,哪個演算法語句執行次數越多,它消耗時間越多。乙個演算法中的語句執行次數稱為語句頻度或者時間頻度,記為t(n)。
時間頻度簡要說明
@test
// 計算 1 + 2 + 3 …… + 99 + 100
public
void
method1()
system.out.
println
(total);}
@test
// 計算 1 + 2 + 3 …… + 99 + 100
public
void
method2()
演算法的時間複雜度可以忽略常數項。2n+5 隨著n逐漸增加,執行曲線無限接近
3n+10 隨著n逐漸增加,執行曲線無限接近
同理:可以忽略低次項 、忽略係數。比如 t(n) = 2n2 與 t(n) = 2n2 +3n,可以忽略低次項。比如 t(n) = 3n2 與 t(n) = 2n2 當n越來越大,係數也可以忽略。
時間複雜度簡要說明:
1、一般情況下,演算法中的基本操作語句的重複執行次數是問題規模n的某個函式,使用t(n)表示。若有某個輔助函式f(n),使得當n趨近於無窮大時,t(n)/f(n)的極限值為不等於0的常數,則稱f(n)是t(n)的同數量級函式,記作t(n)= o(f(n)) ,稱o(f(n))為演算法的漸進時間複雜度,簡稱時間複雜度。
2、t(n)不同,但是時間複雜度可能相同,比如 t(n) = n2+7n+6與t(n) = 2n2+3n+1,他們的t(n)不同,但是時間複雜度相同,都是o(n2)
3、計算時間複雜的方法
3.1、使用常數1代替執行時間中的所有加法常數。
3.2、修改後得到執行次數函式中,只保留最高端項。
3.3、去除高階項的係數。
常見的時間複雜度
1、常數階o(1)
2、對數階o(log2
n\log_2 n
log2n
)3、線性階o(n)
4、常數對數階o(nlog2
n\log_2 n
log2n
)5、平方階o(n2)
6、立方階o(n3)
7、k次方階o(nk)
8、指數階o(2n)
常見的演算法時間複雜度,由小到大依次為:o(1) < o(log2
n\log_2 n
log2n
) < o(n) < o(nlog2
n\log_2 n
log2n
) < o(n2) < o(n3) < o(nk) < o(2n),隨著問題規模n的不斷增大,上述時間複雜度不斷增大,演算法的執行效率越低,應該盡可能避免使用指數階的演算法。簡要示意圖如下:
常見的時間複雜度舉例說明:
常數階o(1)
// 常數階 無論**執行了多少行,只要沒有迴圈等複雜結構,那麼這個**的時間複雜度都是o(1)
public
voidm1(
)
2、對數階o(log2
n\log_2 n
log2n
)
// 對數階說明
public
voidm2(
int n)
}
對數階簡要說明:
在while迴圈中,每次都將i乘以2,i的值與n越來越接近。假設迴圈k次,i就大於n了,此時這個迴圈就退出了,也就是說2k >= n,那麼 k = log2
n\log_2 n
log2n
,當迴圈log2
n\log_2 n
log2n
次以後,**就結束向下執行。所以這段**的時間複雜度為o(log2
n\log_2 n
log2n
)。假設,**修改為i = i * 3;
此時的時間複雜度為o(log3
n\log_3 n
log3n
)。如果 n = ax (a > 0,a ≠
\neq
= 1),即a的x次方等於n(a > 0,a ≠
\neq
= 1),那麼數x就是以a為底n的對數,記作 x = loga
n\log_a n
logan
,a是對數的底數,n是真數,x是「以a為底n的對數」。
線性階
// 線性階說明
public
voidm3(
int n)
}
線性對數階
// 線性對數階說明
// 線性對數階其實就是將對數階**迴圈了n遍
public
voidm4(
int m,
int n)
}}
平方階
// 平方階
public
voidm5(
int n)
}}
平均時間複雜度和最壞時間複雜度1、平均時間複雜度是指所有可能的輸入例項以等概率出現的情況下,該演算法的執行時間。
2、最壞情況下的時間複雜度是最壞時間複雜度,一般討論的時間複雜度是最壞情況下的時間複雜度,這樣做的原因是:最壞情況下的時間複雜度,是演算法在任何例項上執行時間的界限,這就保證了演算法的執行時間不會比最壞情況更長。
3、排序演算法的時間複雜度如下圖所示。
排序演算法
平均時間
最壞情況
穩定度額外空間
備註氣泡排序
o(n2)
o(n2)
穩定o(1)
n小時較好
交換排序
o(n2)
o(n2)
不穩定o(1)
n小時較好
選擇排序
o(n2)
o(n2)
不穩定o(1)
n小時較好
插入排序
o(n2)
o(n2)
穩定o(1)
大部分已經排序好時較好
基數排序
o(logr
b\log_r b
logrb
)o(logr
b\log_r b
logrb
)穩定o(1)
b是真數,r是基數
希爾排序
o(nlogn)
o(ns) 1不穩定
o(1)
s是所選分組
快速排序
o(nlogn)
o(n2)
不穩定ologn
n大時較好
歸併排序
o(nlogn)
o(nlogn)
穩定o(n)
n大時較好
堆排序o(nlogn)
o(nlogn)
不穩定o(1)
n大時較好
學習Python的第六節課 函式和變數作用域
函式的本質就是一段有特定功能 可以重複使用的 1 內建函式python自帶的可直接呼叫的函式。比如 int input print 2 庫函式 庫函式匯入 import 模組名 from 模組名 import 執行過程 先判斷表示式的值,當其值為true或其他非0值,執行語句塊1,否則執行語句塊2。...
資料結構和演算法學習六,之非遞迴排序
在上面一篇部落格當中,我們發現普通查詢和排序查詢的效能差別很大。作為乙個100萬的資料,如果使用普通的查詢方法,那麼每乙個資料查詢平均下來就要幾十萬次,那麼二分法的查詢呢,20多次就可以搞定。這中間的差別是非常明顯的。既然排序有這麼好的效果,那麼這篇部落格中,我們就對排序算做乙個總結。按照我個人的理...
資料結構和演算法學習六,之非遞迴排序
在上面一篇部落格當中,我們發現普通查詢和排序查詢的效能差別很大。作為乙個100萬的資料,如果使用普通的查詢方法,那麼每乙個資料查詢平均下來就要幾十萬次,那麼二分法的查詢呢,20多次就可以搞定。這中間的差別是非常明顯的。既然排序有這麼好的效果,那麼這篇部落格中,我們就對排序算做乙個總結。按照我個人的理...