第二章 演算法基礎

2021-07-23 06:33:45 字數 3980 閱讀 8301

2.1 插入排序(insertion-sort):

時間複雜度:o(n²)

對於少量元素的排序,是乙個有效的演算法。

為什麼叫插入排序呢?

可以模擬撲克牌整牌

將未排序的數字通過遍歷插入到已排好序的數字中的對應位置

如何實現呢

num[j+1]=key;//插入

}for(int i=1;i<=n;i++)

printf("\n");

return

0;}迴圈不變式:以插排舉例後引入了迴圈不變式的概念

第二章原文是這樣說的:

每次迴圈從陣列a中取出第j個元素插入有序區a[1 .. j-1],然後遞增j。這樣a[1 .. j-1]的有序性始終得到保持,這就是所謂的「迴圈不變 (loop invariant)」了

恕本人愚鈍,看不太懂

只能理解為迴圈體的遍歷定義域,歡迎指正==

不過它的性質還是很好理解和應用的

1 , 初始化:迴圈的第一次迭代之前,它為真

2,保持 :如果迴圈的某次迭代之前它為真,那麼下次迭代之前它仍為真

3,終止 :在迴圈終止時,不變式為我們提供乙個有用的性質,該性質有助於證明演算法是正確的

偽**:

為使用最清晰、最簡潔的表示方式來說明給定的演算法,於是有了偽**

偽**為更簡潔的表達演算法本質,常常忽略資料抽象、模組性和錯誤處理的問題 //為了方便debug,模組性很重要

傳參 在第12頁第四段有這麼幾句話:

被呼叫過程接收其引數自身的副本。

如果它對某個引數賦值,呼叫過程看不到這種改變。

例如,如果x是某個被呼叫過程的引數,在被呼叫過程中的賦值x=y對呼叫過程是不可見的。

這幾句話很晦澀,其實就講了乙個很簡單的問題:

當作為乙個實參傳參進入乙個函式時,是複製了那個引數的乙個副本傳了進去,函式內對該引數的各種操作對原引數是沒有影響的,不會使其發生改變,而如果是將位址傳進去,那麼函式對其的操作會使其發生改變

2.2 分析演算法:

分析演算法的結果意味著**演算法需要的資源(時間、空間)

演算法分析不關注演算法實際的執行時間,而是關注執行時間的增長

分析演算法,包括最佳情況,平均情況和最壞情況

但我們一般只討論最壞情況,原因如下:

1,乙個演算法最壞情況執行時間給出了任何輸入的執行時間的乙個上界

2,對某些演算法,最壞情況經常出現

3,平均情況往往和最壞情況大致一樣差

只說下第三條==

以插排為例,平均情況為n/2,最壞情況為n,數量級均為n,當我們討論演算法是,是關注演算法執行時間的增長,即數量級,所以他們是相等的

下面試分析乙個簡單的程式(求i³之和)

int 

sum(int n)

宣告不計時間。

第1行和第4行各佔乙個時間單元。

第3行每執行一次占用四個時間單元(兩次乘法,一次加法,一次賦值)

第2行在初始化i,測試i<=n和對i的自增運算中隱含著開銷。這些所有開銷為初始化乙個時間單元,所有的測試n+1個時間單元,以及所有的自增運算n個時間單元,共2n+2。

忽略呼叫函式與返回值的開銷,總共為6n+4。所以說該函式為o(n)。

2.3設計演算法

分治法的思想:

*將原問題分解為幾個規模較小但類似於原問題的子問題,遞迴地求解這些子問題,然後再合併這些子問題的解來建立原問題的解*

//分治的思想博大精深,非常重要,第四章還會再詳細討論

//我會告訴你我就是因為分治,遞迴沒學好才下決心啃算導的嘛(:зゝ∠)

分治模式在每層遞迴時都有三個步驟:

分解原問題為若干子問題,這些子問題是原問題規模較小的例項

解決這些子問題,遞迴地求解各子問題。若子問題的規模足夠小,則直接求解

合併這些子問題的解成原問題的解

下面以歸併排序為例解釋

分解:分解待排序的n個元素的序列成各具n/2個元素的兩個子串行

解決:使用歸併排序遞迴地排序兩個子串行

合併:合併兩個已排序的子串行以產生已排序的答案

歸併排序:

主要思想

for(int i=1;i<=n2;i++)//賦值

l[n1+1]=maxnum;//哨兵標記

r[n2+1]=maxnum;

int i=1,j=1;

for(int k=p;k<=r;k++)//並

else

}return;

}void mergesort(int *a,int p,int r)

return ;

}int main()

mergesort(a,1,n);

for(int i=1;i<=n;i++)

int x;

scanf("%d",&x);

return

0;}下面看一下遞迴樹

這個樹的深度是logn,所以層數是logn+1

而每層的時間是cn

所以總時間就是cn*(logn+1)=cnlogn+cn

所以時間複雜度為nlogn

求最大子列和nlogn實現

#include

#include

#include

using

namespace

std;

int max3(int a,int b,int c)

int maxsubsum(int a,int left,int right)

int maxrightbordersum=0;

int rightbordersum=0;

for(int i=center+1;i<=right;i++)

return max3(maxleftsum,maxrightsum,maxleftbordersum+maxrightbordersum);

}int main()

int ans=maxsubsum(a,0,n-1);

printf("%d\n",ans);

return

0;}

以上所有 如有錯漏 歡迎打臉

第二章 演算法基礎

引言 演算法導論 在本章將向我們介紹乙個演算法設計和分析框架,在後續的章節也將在這個框架的基礎上來分許演算法。名詞解釋 1 偽 偽 就是以最清晰 最簡潔的表示方法來說明演算法,而忽略資料抽象 模組性和錯誤處理的問題 2 迴圈不變式 每次迴圈從陣列a中取出第j個元素插入有序數列a 1 j 1 然後遞增...

第二章 演算法基礎

本章首先講了插入排序演算法,然後分析了插入排序演算法的時間複雜性,引出了分治法的設計思想,分析了分治演算法。1.插入排序 插入排序採用了增量演算法 在排序子陣列a 1.j 1 後,將單個元素a j 插入到子陣列的適當位置,產生排序好的子陣列a 1.j 1 package sort 23 import...

第二章 演算法

本章內容了解即可。如果大家對資料結構完全不了解,我建議你先去看一下b站上郝斌老師的課程。演算法是解決特定問題求解步驟的描述,在計算機中表現為指令的優先序列,並且每條指令表示乙個或多個操作。只聽資料結構課程,當然可以,但是聽完後你可能沒有什麼感覺,因為你不知道他是幹嘛的。但是如果配合演算法來講解,你就...