演算法學習(一)
不論學習有多忙,也要抽空讀點書。
演算法
什麼是演算法?
有一個很著名的公式 “程式=資料結構+演算法”。
曾經跟朋友吃飯的時候我問他什麼是演算法,他說演算法嘛,就是一套方法,需要的時候拿過來,套用就可以,我吐槽他,他說的是小學數學題的演算法,不是程式設計的演算法。
演算法,從字面意義上解釋,就是用於計算的方法,通過該這種方法可以達到預期的計算結果。目前,被廣泛認可的演算法專業定義是:演算法是模型分析的一組可行的,確定的,有窮的規則。通俗的說,演算法也可以理解為一個解題步驟,有一些基本運算和規定的順序構成。但是從計算機程式設計的角度看,演算法由一系列求解問題的指令構成,能根據規範的輸入,在有限的時間內獲得有效的輸出結果。演算法代表了用系統的方法來描述解決問題的一種策略機制。
完成同一件事的不同的演算法完成的時間和佔用的資源可能並不相同,這就牽扯到效率的問題。演算法的基本任務是針對一個具體的問題,找到一個高效的處理方法,從而完成任務。而這就是我們的責任了。
演算法的五個特徵:
一個典型的演算法一般都可以抽象出5個特徵:
有窮性:演算法的指令或者步驟的執行次數和時間都是有限的。
確切性:演算法的指令或步驟都有明確的定義。
輸入:有相應的輸入條件來刻畫運算物件的初始情況。
輸出:一個算應有明確的結果輸出。
可行性:演算法的執行步驟必須是可行的。
演算法的分類:
根據應用分:
按照演算法的應用領域,可以分為基本演算法,資料結構相關演算法,幾何演算法,圖論演算法,規劃演算法,數值分析演算法,加密解密演算法,排序演算法,查詢演算法,並行演算法,數值演算法……
根據確定性分:
確定性演算法:有限時間內完成,得到結果唯一。
非確定性演算法:有限時間內完成,得到結果不唯一,存在多值性。
根據演算法的思路分:
遞推演算法,遞迴演算法,窮舉演算法,貪婪演算法,分治演算法,動態規劃演算法,迭代演算法等。
演算法和公式的關係
演算法>=公式
如果沒有接觸到程式設計,的確很容易將演算法理解為數學公式。公式的確具備演算法的特徵,但是演算法並不等於公式,公式是一種高度精簡的演算法,演算法的形式可以比公式更復雜,解決的問題更加廣泛。
演算法和程式的關係 程式也是演算法的一種表現形式,也是一種工具
演算法和資料結構的關係
資料結構是資料的組織形式,可以用來表現特定的物件資料。
因為不同的資料結構所採用的處理方法不同,計算的複雜程度也不同,因此演算法往往依賴於某種某種資料結構。資料結構是演算法實現的基礎。
演算法的表示:
自然語言表示:
就是用我們的口頭語言來表示演算法,這樣很多演算法難以描述,不利於發展交流。
流程圖表示:
一般有三種流程結構:
順序結構,分支結構,迴圈結構
N-S圖表示:
NS圖也叫作盒圖或者CHAPIN圖,是用於取代傳統流程圖的一種描述方式。 以 SP方法為基礎,NS圖僅含有下圖4.61 的5種基本成分,它們分別表示SP方法的幾種標準控制結構。
偽程式碼表示:
虛擬碼並不是程式程式碼,虛擬碼介於自然語言和程式設計用語言之間,是將演算法描述成類似程式語言的一種形式。
演算法的效能評價
演算法的效率作為判斷演算法優劣的標準。
一個演算法的優劣往往通過演算法複雜度來衡量,演算法複雜度包括時間複雜度和空間複雜度兩個方面。其作用:時間複雜度是指執行演算法所需要的計算工作量;而空間複雜度是指執行這個演算法所需要的記憶體空間。(演算法的複雜性體現在執行該演算法時的計算機所需資源的多少上,計算機資源最重要的是時間和空間(即暫存器)資源,因此複雜度分為時間和空間複雜度)。
時間複雜度
即通常所說的演算法執行所需要耗費的時間,時間越短,演算法越好。
計算方法
1.一般情況下,演算法中基本操作重複執行的次數是問題規模n的某個函式,用T(n)表示,若有某個輔助函式f(n),使得當n趨近於無窮大時,T(n)/f(n)的極限值為不等於零的常數,則稱f(n)是T(n)的同數量級函式。記作T(n)=O(f(n)),稱O(f(n)) 為演算法的漸進時間複雜度,簡稱時間複雜度。
分析:隨著模組n的增大,演算法執行的時間的增長率和 f(n) 的增長率成正比,所以 f(n) 越小,演算法的時間複雜度越低,演算法的效率越高。
2. 在計算時間複雜度的時候,先找出演算法的基本操作,然後根據相應的各語句確定它的執行次數,再找出 T(n) 的同數量級(它的同數量級有以下:1,log2n,n,n log2n ,n的平方,n的三次方,2的n次方,n!),找出後,f(n) = 該數量級,若 T(n)/f(n) 求極限可得到一常數c,則時間複雜度T(n) = O(f(n))。
1 for(i=1; i<=n; ++i) {
2
3 for(j=1; j<=n; ++j) {
4
5 c[i][j] = 0;//該步驟屬於基本操作執行次數:n的平方次
6
7 for(k=1; k<=n; ++k)
8
9 c[i][j] += a[i][k] * b[k][j];//該步驟屬於基本操作執行次數:n的三次方次
10
11 }
12
13 }
則有 T(n) = n 的平方+n的三次方,根據上面括號裡的同數量級,我們可以確定 n的三次方 為T(n)的同數量級
則有 f(n) = n的三次方,然後根據 T(n)/f(n) 求極限可得到常數c
則該演算法的時間複雜度:T(n) = O(n^3) 注:n^3即是n的3次方。
空間複雜度
空間複雜度可以分為兩個方面:
1.程式儲存所需要的儲存空間,也就是程式的大小。
2.程式在執行過程中所需要消耗的儲存空間資源,如程式在執行過程中的中間變數等。
簡單演算法例項:
隨機生成一個20個整數資料的陣列,然後輸入要查詢的數,然後用順序查詢法:
虛擬碼:
變數X<-輸入待查詢的資料
變數arr<-隨機生成資料陣列
for 1 to 20
if arr[i] ==x
break;找到資料
else
輸出該資料的位置
程式結束
1 import java.util.Random;
2 import java.util.Scanner;
3
4 public class P1_1 {
5 static int N=20;
6 public static void main(String[] args) {
7 int[] arr=new int[N];
8 int x,n,i;
9 int f=-1;
10
11 Random r=new Random(); //隨機種子
12 for(i=0;i<N;i++)
13 {
14 arr[i]=r.nextInt(100); //產生陣列
15 }
16
17 System.out.print("隨機生成的資料序列:n");
18 for(i=0;i<N;i++)
19 {
20 System.out.print(arr[i]+" "); //輸出序列
21 }
22 System.out.print("nn");
23
24 System.out.print("輸入要查詢的整數:");
25 Scanner input=new Scanner(System.in);
26 x=input.nextInt(); //輸入要查詢的數
27
28 for(i=0;i<N;i++) //順序查詢
29 {
30 if(x==arr[i]) //找到資料
31 {
32 f=i;
33 break;
34 }
35 }
36
37
38 if(f<0) //輸出查詢結果
39 {
40 System.out.println("沒找到資料:"+x);
41 }
42 else
43 {
44 System.out.print("資料:"+x+" 位於陣列的第 "+(f+1)+" 個元素處.n");
45 }
46
47 }
48
49 }