標籤:自然數 序列 col size 排序 輸入 問題 次數 實施
C++ 演算法
演算法概念
演算法是特定問題求解步驟的描述
在電腦中表現為指令的有限序列
演算法是獨立存在的一種解決問題的方法和思想。
對於演算法而言,語言並不重要,重要的是思想。
演算法和資料結構區別
資料結構只是靜態描述了資料元素之間的關係
高效的程式需要在資料結構的基礎上設計和選擇演算法
程式=資料結構+演算法
總結:
演算法是為瞭解決實際問題而設計的
資料結構是演算法需要處理的問題載體
資料結構與演算法相輔相成
演算法特性
輸入
演算法具有0個或多個輸入
輸出
演算法至少有1個或多個輸出
有窮性
演算法在有限的步驟之後會自動結束而不會無限迴圈
確定性
演算法中的每一步都有確定的含義,不會出現二義性
可行性
演算法的每一步都是可行的
演算法效率的度量
1、事後統計法
比較不同演算法對同一組輸入資料的運行處理時間
缺陷
為了獲得不同演算法的已耗用時間必須編寫相應程式
已耗用時間嚴重依賴硬體以及運行時的環境因素
演算法的測試資料的選取相當困難
事後統計法雖然直觀,但是實施困難且缺陷多。
2、事前分析估算
依據統計的方法對演算法效率進行估算
影響演算法效率的主要因素
演算法採用的策略和方法
問題的輸入規模
編譯器所產生的代碼
電腦執行速度
#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <string>//演算法最終編譯成具體的電腦指令//每一個指令,在具體的電腦上運行速度固定//通過具體的n的步驟,就可以推匯出演算法的複雜度long sum1(int n){ long ret = 0; int* array = (int*)malloc(n * sizeof(int)); int i = 0; for(i=0; i<n; i++) { array[i] = i + 1; } for(i=0; i<n; i++) { ret += array[i]; } free(array); return ret; }long sum2(int n){ long ret = 0; int i = 0; for(i=1; i<=n; i++) { ret += i; } return ret;}long sum3(int n){ long ret = 0; if( n > 0 ) { ret = (1 + n) * n / 2; } return ret;}void mytest(){ printf("%d\n", sum1(100)); printf("%d\n", sum2(100)); printf("%d\n", sum3(100)); return;}int main(){ mytest(); system("pause"); return 0;}
int func(int a[], int len){ int i = 0; int j = 0; int s = 0; for(i=0; i<len; i++) n { for(j=0; j<len; j++) n { s += i*j; //n*n } } return s; }//n*n
注意1:判斷一個演算法的效率時,往往只需要關注運算元量的最高次項,其它次要項和常數項可以忽略。
注意2:在沒有特殊說明時,我們所分析的演算法的時間複雜度都是指最壞時間複雜度。
2、大O標記法
演算法效率嚴重依賴於操作(Operation)數量
在判斷時首先關注運算元量的最高次項
運算元量的估算可以作為時間複雜度的估算
O(5) = O(1)
O(2n + 1) = O(2n) = O(n)
O(n2+ n + 1) = O(n2)
O(3n3+1) = O(3n3) = O(n3)
常見時間複雜度
關係
3、演算法的空間複雜度
演算法的空間複雜度通過計算演算法的儲存空間實現
S(n) = O(f(n))
其中,n為問題規模,f(n))為在問題規模為n時所佔用儲存空間的函數
大O標記法同樣適用於演算法的空間複雜度
當演算法執行時所需要的空間是常數時,空間複雜度為O(1)
空間與時間的策略
多數情況下,演算法執行時所用的時間更令人關注
如果有必要,可以通過增加空間複雜度來降低時間複雜度
同理,也可以通過增加時間複雜度來降低空間複雜度
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <string.h>/* 問題: 在一個由自然數1-1000中某些數字所組成的數組中,每個數字可能出現零次或者多次。 設計一個演算法,找出出現次數最多的數字。*/// 方法1: 排序,然後找出出現次數最多的數字// 排序,然後找出出現次數最多的數字// 方法2: 把每個數字出現的次數的中間結果,緩衝下來;在緩衝的結果中求最大值void search(int a[], int len){ int sp[1000] = {0}; int i = 0; int max = 0; for (i = 0; i < len; i++) { int index = a[i] - 1; sp[index]++; } for (i = 0; i < 1000; i++) { if (max < sp[i]) { max = sp[i]; } } for (i = 0; i < 1000; i++) { if (max == sp[i]) { printf("%d\n", i + 1); } }}void mytest(){ int array[] = {1, 1, 3, 4, 5, 6, 6, 6, 2, 3}; search(array, sizeof(array)/sizeof(array[0])); return;}int main(){ mytest(); system("pause"); return 0;}
C++ 演算法