演算法一(時間複雜度,冒泡,選擇,插入,對數器)

2021-09-04 13:14:00 字數 3106 閱讀 7926

目錄

時間複雜度的巨集觀解釋:

常數時間操作:

時間複雜度的定義:

氣泡排序:

選擇排序:

插入排序:

對數器:

額外空間複雜度:

主要用來衡量演算法的好壞。我們寫好了乙個演算法,假設這個演算法是正確的,我們如何來衡量這個演算法的效能?怎麼樣去判斷這個演算法是乙個好的演算法,還是乙個壞的演算法,時間複雜度就是其中乙個非常重要的指標,這是對於是時間複雜度的巨集觀上的解釋。

乙個操作如何和資料量沒有關係,每次都是固定時間內完成,這樣的操作叫做常數操作。比如陣列定址操作,為運算操作,加減乘除操作,比較操作 。

時間複雜度是乙個演算法流程中,常數運算元量(在最差情況下)的指標,常常使用o(n)來表示。集體來說,在常數運算元量的表示式中,只要高階項,不要低階項,也不要高階項的係數,剩下的部分如果記為f(n),那麼時間複雜度為o(f(n))。

評價乙個演算法的好壞,先看時間複雜度的指標,也就是冪,然後再分析不同資料樣本下的實際執行時間,也就是常數項

我們舉乙個例子來說明上述的定義:

以常見的選擇排序為例:先解釋一下什麼是選擇排序,假設現在有 n 個數,要對這 n 個數進行排序,如下

①:在0~n-1的位置上尋找最小值,放在0 位置上,這裡需要進行n - 1次比較操作,

②:在1~n-1的位置上尋找最小值,放在1 位置上,這裡需要進行 n - 2 次比較操作

③:在2~n-1的位置上尋找最小值,放在2的位置上,這裡需要進行 n - 3次的比較操作

第n -1 次,最大的元素放置於 n - 1的位置。這就完成了對於n個數的排序操作。

這裡我們將n -1次的常數操作累加起來,(n-1)+ (n -2)+ (n - 3)+ ..... + 2 + 1 =  (1 + (n - 1))*  (n - 1)/ 2 ,按照等差數列的求和公式得到,可以抽象為 a * n ^ 2 + b * n + c 的形式,此時我們不要低階項,不要高階項,剩下的部分就是就

f(n)=  n^2 ,那麼時間複雜度就是 o( f(n ^2))

再舉例子:二分查詢的時間複雜度,我們的二分查詢是相對於有序的陣列而言的,假設我們現在有陣列,

number:1,3,4,6,7,10.12

index :0,1,2,3,4, 5, 6

假設我們現在尋找 3 所在的索引,方法①,我們直接遍歷資料,每次遍歷乙個數都進行比較操作,常數時間的操作,在n個數中找到 元素 x 的位置的話,時間複雜度我 o(n);方法②:每次尋找 0,和 n - 1位置的中間索引 (n / 2) 位置的元素假設為 y,比較 y 和 x 的大小,如果比x大,去右邊找,否則去左邊找,不斷的迴圈知道找到該元素,或者沒有該元素。這裡不斷的進行二分,n可以被2分多少次呢? 即 log (n)要進行 log(n)次的比較操作,所以時間複雜度是 log (n)。所以二分查詢的時間複雜度是 log (n)。這裡如果沒有指定以誰為底的時候,預設就是以2 為底的。

再舉例子:

乙個有序陣列a,另乙個無序陣列b,請列印b中的所有不在a中的數,a數 組長度為n,b陣列長度為m。演算法流程:先把陣列b排序,然後用類似外排的方式列印所有在a中出現的數;

第一步:基於比較的排序最優可以做到o(m * log m),所以將無序的陣列排序的時間複雜度為o(m * log m),然後將兩個有序的陣列排序的過程,可以使用外部排序。外部排序的使用場景是兩個已經有序的陣列,分別使用兩個指標來記錄兩個陣列的index,然後依次順序比對兩個指標指向的元素的值,將其放入到輔助陣列中,直到其中乙個陣列到達最後乙個元素。所以外部排序的每次比較操作是常數時間的,那麼時間複雜度為o(n)級別的。所以最終,完成該演算法的時間複雜度就是:

o(m * log m) + o(n + m)

這裡面,我們看出這裡有兩個樣本量, 此時,我們需要根據樣本量來化簡時間複雜度的表示式。三個例子希望你已經理解了時間複雜度的概念。接下來是時間排序演算法的練習:

氣泡排序是嚴格的時間複雜度為o(n^2)的排序演算法,實現**如下:

氣泡排序 + 對數器

選擇排序也是嚴格的時間複雜度為o(n^2)的排序演算法,實現**如下:

選擇排序 + 對數器

我們來一起分析一下插入排序的時間複雜度,假如資料是1,2,3,4,5,對於氣泡排序和選擇排序來說都是嚴格的o(n^2)的演算法,但是對於插入排序來說,是o(n)的演算法,因為每次比較之後,直接跳出迴圈。但是對於5,4,3,2,1這樣的資料,插入排序演算法的時間複雜度又退化成了o(n^2)的演算法。那麼我們應該怎麼去評估類似這樣的演算法的時間複雜度的好壞呢?

一律按照最快的情況去評估

實現**:

插入排序 + 對數器 

對數器主要有三個作用:

①:主要用來評測我們的演算法的正確性;

②:找到易於分析的錯誤案例,來分析我們的演算法出錯在**

③:證明貪心策略的正確和錯誤

對數器的要點:

①:產生隨機樣本的產生器

②:寫乙個絕對正確的方法(通常是易於實現的)

③:大樣本測試 

詳細版本:

0,有乙個你想要測的方法a,

1,實現乙個絕對正確但是複雜度不好的方法b,

2,實現乙個隨機樣本產生器

3,實現比對的方法

4,把方法a和方法b比對很多次來驗證方法a是否正確。

5,如果有乙個樣本使得比對出錯,列印樣本分析是哪個方法出 錯

6,當樣本數量很多時比對測試依然正確,可以確定方法a已經 正確。

具體的例子看上面的排序演算法中對數器的寫法。

你這個演算法流程在跑的過程中,需要申請多大的空間才能使得這個演算法跑下去;

上訴的幾個例子中,我們對元陣列進行排序的操作,申請的空間就是幾個額外的變數而已,比如 int i,int j ,int end 等,所以說額外的空間複雜度是o(1),在比如如果要完成某個演算法,我們需要額外申請乙個等長度的陣列,那麼我們的額外空間複雜度就是o(n)。

演算法(一)時間複雜度

演算法很重要,但是一般情況下做移動開發並不經常用到,所以很多同學早就將演算法打了個大禮包送還給了老師了,況且很多同學並沒有學習過演算法。這個系列就讓對演算法頭疼的同學能快速的掌握基本的演算法。過年放假階段玩了會遊戲nba2k17的生涯模式,沒有比賽的日子也都是訓練,而且這些訓練都是自發的,沒有人逼你...

演算法(一)時間複雜度

1.演算法的效率 雖然計算機能快速的完成運算處理,但實際上,它也需要根據輸入資料的大小和演算法效率來消耗一定的處理器資源。要想編寫出能高效執行的程式,我們就需要考慮到演算法的效率。演算法的效率主要由以下兩個複雜度來評估 時間複雜度 評估執行程式所需的時間。可以估算出程式對處理器的使用程度。空間複雜度...

一 時間複雜度

一 時間複雜度計算規則 1.基本操作,即只有常數項,其時間複雜度為o 1 比如if,print 與規模n無關 2.順序結構 按加法計算 3.迴圈結構,按乘法計算 4。分支結構,時間複雜度取最大值。二 常見時間複雜度與大小關係 常數項 o 1 12線性項 o n 2n 3平方項 o n 2 4n 3 ...