數據結構與演算法(一)

来源:https://www.cnblogs.com/haohuihai/archive/2020/06/27/13199030.html
-Advertisement-
Play Games

演算法效率的度量方法; 函數調用的時間複雜度分析; 常見的時間複雜度; 演算法的空間複雜度; ...


演算法效率的度量方法:

1. 事後統計方法:通過設計好的測試程式和數據,利用電腦計時器對不同演算法編製的程式的運行時間進行比較,從而確定演算法效率的高低。

缺陷:是根據以及編製好的程式去測試,如果測試的是糟糕的演算法,會功虧一簣。

2. 事前分析估算方法:在電腦程式編寫前,依據統計方法對演算法進行估算。

高級語言編寫的程式在電腦上運行時所消耗的時間取決於下列因素:

  1. 演算法採用的策略,方案。
  2. 編譯產生的代碼質量
  3. 問題的輸入規模
  4. 機器執行指令的速度

所以:一個程式的運行時間依賴於演算法的好壞和問題的輸入規模。

 在編寫程式的時候,我們不關心語言、所用的電腦只關心它所實現的演算法。

在分析程式的運行時間的時候,最重要的是把程式看成是獨立於程式設計語言的演算法或一系列步驟,把基本操作的數量和輸入模式進行關聯。

 函數漸進增長:

n=1時,演算法A1效率不如演算法B1;當n=2時,兩者效率相等;當n>2時,演算法A1開始優於演算法B1,隨著n的繼續增加,演算法A1比演算法B1逐漸拉大差距。所以總體上演算法A1比演算法B1優秀

定義:給定2個函數f(n)和g(n),如果存在一個整數N,使得對於所有的n>N,f(n)總是比g(n)大,那麼,我們說f(n)的增長漸進快於g(n)

例如如下演算法的增長率:

 

 

通過這組數據可以看出,當n的值非常大的時候,3n+1已經不能和2n^2的結果進行比較,最終幾乎是可以忽略不計的,演算法G在跟演算法I基本已經重合了,

結論:判斷一個演算法的時候,函數中的常數和其他次要項常常可以忽略,關註主項(最高項)的階數。

註意:不能通過少量的數據來判斷一個演算法的好壞。

 演算法時間複雜度:
定義:在進行演算法分析時,語句總的執行次數T(n)是關於問題規模n的函數,進而分析T(n)隨n的變化情況並確定T(n)的數量級,演算法的時間複雜度,也就是演算法的時間量度,記作:T(n)=O(f(n))。他表示隨問題規模n的增大,演算法執行時間的增長率和f(n)的增長率相同,稱作演算法的漸進時間複雜度,簡稱為時間複雜度,其中f(n)是問題規模n的某個函數。

用大O()來體現演算法時間複雜度的記法,一般情況下隨著輸入規模n的增大,T(n)增長最慢的演算法為最優演算法。

 推導大O階的方法

  1. 用常數1取代運行時間中的所有加法常數。
  2. 在修改後的運行函數中,只保留最高項。
  3. 如果最高項存在且不是1,則除這個項相乘的常數。
  4. 得到的最後的結果就是O()階

例如:

1.常數階

int sum=0,n=100;

printf("hello word\n");

printf("hello word\n");

printf("hello word\n");

printf("hello word\n");

sum=(1+n)*n/2

所有常數項均可以看做是1,時間複雜度為O(1);

 2.線性階:

含有非嵌套迴圈涉及線性階,就是隨著問題規模n的擴大,對應計算次數呈直線增長。

int i,n=100,sum=0;

for(i=0;i<n;i++){

sum=sum+i;

}

迴圈中的代碼需要執行n次,所以時間複雜度為O(n)

 3.平方階:

int i,j,n=100;
for(i=0;i<n;i++)
{   
for(j=0;j<n;j++){   printf("hello word")   } }

外層執行一次,內層執行100次,需要執行100*100次,n的平方次,所以時間複雜度為O(n^2),

如果有三個這樣的迴圈,則時間複雜度為O(n^3)

分析下,由於當i=0時,內迴圈執行了n次,當i=1時,內迴圈則執行n-1次.....當i=n-1時,內迴圈執行1次,所以總的執行次數應該是:- n+(n-1)+(n-2)+...+1 = n(n+1)/2,用我們推導大O的攻略,第一條忽略,因為沒有常數相加。第二條只保留最高項,所以n/2這項去掉。第三條,去除與最高項相乘的常數,最終得O(n^2)。

 4.對數階

int i=1,n=100;
while(i<n){
i=i*2;
}

由於2^x=n得到x=log(2)n,所以這個迴圈的時間複雜度為O(log(2)n)

 函數調用的時間複雜度分析:

例1:

int i,j;
for(i=0;i<n;i++){

function(i);

}

void function(int count){

printf("%d",count);

}

 函數體是列印這個參數,function函數的時間複雜度是O(1),所以整體的時間複雜度就是迴圈的次數O(n)。

例2:

void function(int count){

int j;

for(j=count;j<n;j++){

printf("%d",j);
}
count++;
}

function內部的迴圈次數隨count的增加而減少,所以它的時間複雜度為O(n^2)。

 例3:

n++; ##1

function(n);##一個內部迴圈的函數 O(N^2)
for(i=0;i<n;i++){ function(i);##內部迴圈的函數 } ## O(N^2)   for(i=0;i<n;i++){   for(j=i;j<n;j++){   printf("%d",j);   }}##O(n^2)

時間複雜度為O(n^2)

 常見的時間複雜度:

常用時間複雜度所耗費的時間從小到大依次是:

O(1)<O(logn)<(n)<O(nlogn)<O(n^2)<O(n^3)<O(2^n)<O(n!)<O(n^n)

最壞情況與平均情況:

演算法的分析也是類似,我們查找一個有n個隨機數字數組中的某個數字,最好的情況是第一個數字就是,那麼演算法的時間複雜度為O(1),但也有可能這個數字就在最後一個位置,它的時間複雜度為O(n),平均運行時間是期望的運行時間,最壞的運行時間是一種保證,在應用中,這是一種最重要的需求,通常除非特別的指定,我們提到的運行時間都是最壞情況的運行時間。

演算法的空間複雜度:

 演算法的空間複雜度通過計算演算法所需的存儲空間實現,演算法的空間複雜度的計算公式為:S(n)=O(f(n)),其中n為問題的規模,f(n)為語句關於n所占空間的函數。

一般情況"複雜度"指的是時間複雜度 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今天博主再給大家分享一個小項目:MiNi圖書管理系統。用的是Java語言開發的,代碼不多,大概260行左右吧,系統是實現圖書的新增圖書、刪除圖書、借閱圖書、歸還圖書、查看圖書等簡單的功能(後附源代碼)! 首先展示一下運行界面效果圖:運行代碼後,會在控制台顯示如下界面: 然後讓用戶選擇,如果用戶不小心 ...
  • import pandas a=pandas.read_excel() def abc(x): return ','.join(x.values) b=a.groupby(['列名'1])['列名2'].apply(abc) c=b.reset_index() print(c) ...
  • WebSocket 非同步風格伺服器 WebSocket\Server 繼承自 Http\Server,所以 Http\Server 提供的所有 API 和配置項都可以使用。 # ws_server.php class WebSocket { public $server; public functi ...
  • 一.環境要求 安裝java 1.8 以上 命令行運行 java -version 返回版本大於1.8 如果沒有,請安裝java 1.8 二.下載與安裝 下載apktool_x.x.x.jar到本地 官網下載或者 鏡像下載 重命名下載的apktool_x.x.x.jar,改名為apktool.jar ...
  • MongoSpark為入口類,調用MongoSpark.load,該方法返回一個MongoRDD類對象,Mongo Spark Connector框架本質上就是一個大號的自定義RDD,加了些自定義配置、適配幾種分區器規則、Sql的數據封裝等等,個人認為相對核心的也就是分區器的規則實現;弄清楚了其分析 ...
  • 前言 本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯繫我們以作處理。 最近一直在關註百度明星吧,發現很多有趣的帖子,於是我就想用python把這些帖子都爬下來,並對內容進行分析。 本文的知識點: 介紹了mysql資料庫內容插入及提取的簡單應用; ...
  • 在上一篇博文中,主要分析了tomcat的整體架構,通過上一篇的分析可以知道,tomcat主要有兩部分組成,分別為連接器(Connector)和容器(Container)。本文介紹連接器(Connector)。 一、Connector的主要功能 連接器主要用於對外交流,它負責接收外部的請求,然後把請求 ...
  • 1.Math類 Math類在java.lang包下,提供了一系列靜態方法用於科學計算,其方法的參數和返回值一般為double類型。 Math類常用方法: 1.abs:絕對值 2.acos,asin,atan,cos,sin,tan:三角函數 3.sqrt:平方根 4.pow(double a,dou ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...