數據結構篇:空間復雜度和時間復雜度

目錄

1.前言:

?1.1 學習感悟

?1.2 數據結構的學習之路(初階)

2.什么是數據結構和算法

2.1 數據結構和算法的關系

2.2 算法的重要性

2.3 如何衡量算法的好壞

3.時間復雜度

3.1 時間復雜度的概念

3.2 大O的漸進表示法 O()

4.空間復雜度

5. 常見的時間復雜度和空間復雜度計算

5.1 時間復雜度計算

5.2 空間復雜度計算

6.時間復雜度對比圖

7.結語


?

1.前言:

? ? ? ? 1.1 學習感悟

????????本篇文章作為數據結構的開篇,也是對C語言部分結尾的繼承,屬于是承上啟下,數據結構中目前使用的編譯器還是Visual Studio 2022,在正式講之前,說點篇外話,繼上一篇動態內存的管理后,很久沒有更新是因為博主的電腦出了問題,維修了小半個月,再者本人對于數據結構的學習周期比較長,數據結構的難度也相對于C語言高了一個層次,但是我覺得只要認真努力的學下去,武裝自己,然后做對題目,那一刻,先前再怎么苦也值得!當你做對題目,在網站上提交你的代碼通過的時候,肯定會有滿滿的成就感,不是嗎?

? ? ? ? 1.2 數據結構的學習之路(初階)

????????在數據結構的具體學習中,大致分為有:

  1. 對于時間復雜度和空間復雜度的一個基本了解
  2. 順序表
  3. 鏈表
  4. 隊列
  5. 二叉樹
  6. 排序

????????這7大類,數據結構基礎篇主要內容就是這些,包括想要考研的朋友們,王道計算機408中的數據結構中,是線性表(順序表,鏈表),棧,隊列,數組,串,二叉樹,查找,排序。大部分都能包含。如果想要考研的同學看到文章也有一絲絲的收獲,這對我也是很大的鼓舞。在這里,我也不能說數據結構怎么學能學好,我也是在學習的過程中,但是經過了一段時間的初步學習,我認為有三點必須要做到,這樣學數據結構不能說萬無一失,只能說會學的很扎實,思路很順暢,時間相對花的少很多。

  • 多畫圖,對于每個內容的學習都盡量畫圖,它能幫助你很好的構思代碼的整體流程,甚至能夠潛在地培養自己的算法素質,算法能力。
  • 多調試,在C語言學習過程中,應該都是能夠學會如何基本的調試,這里就不過多贅述了,想了解基本方法請移步C語言初階回顧-CSDN博客中有過相關介紹,在初步學習的時候可能會不重視調試,覺得我去百度一下,或者把自己的代碼截圖,復制給AI工具,(文心一言,deepseek)讓著幫忙解析就好了,這是個方法,但不是最好的方法,ai會讓你養成惰性,如果你學會了怎么去調試,那是自己成長的一步,如果再進一步,大部分由于疏忽導致的錯誤能夠通過你親手F10,F5,F11出來解決,那是一件多么舒服的事情,你可以通過自己而不是外部工具去解決,久而久之,你會愛上調試的,會出了bug第一時間不是想AI幫我一下,而是下意識F10,調試是一個基本功!在數據結構的學習中,調試是必不可少的,也是和畫圖同等重要的能力。
  • 了解函數棧幀空間,這在二叉樹的學習中,是一個門檻,如果了解了函數棧幀的相關知識,學起來將事半功倍。像博主本人在學習的過程中,把那一塊知識淡忘了,就會重新去溫故一下,看看曾經寫過的文章,從而知新。忘記正常,記起來就好了。

????????進入正題

2.什么是數據結構和算法

? ? ? ? 在互聯網中,各大社交平臺都在討論數據結構的時候,總會和算法緊密相連,而且我看到過很多互聯網大廠和中廠,算法崗位的學歷起步是要碩士。算法要求之高,那么到底什么是數據結構,什么又是算法。這兩者為什么緊密相連?

2.1 數據結構和算法的關系

????????數據結構,在博主的看來,就是電腦在內存中對存儲數據有不同的結構方式。而算法,就是解決一個或者多個問題的一系列計算步驟,用來把輸入的數據轉化為自己想要結果。所以算法我認為不單單是一種解決問題的方式,更多的還是思維

????????而算法和數據結構的關系可以理解為互相的關系,數據結構給算法提供發揮作用的空間,算法為數據結構進行作用。沒有數據結構,算法發揮不出它的作用,沒有算法,數據結構就沒有問題的解決這一步,兩者共生。我在網絡上也搜到我認為很不錯的觀點,大家可以看看:

2.2 算法的重要性

?2.3 如何衡量算法的好壞

? ? ? ? 算法在對問題解決的過程中,或者說在計算機中運行的時候,是要消耗內存資源和空間的。以及要花費一定時間。那這里其實已經指出了衡量算法優劣的兩個標準,這也是面試官常考的點:

? ? ? ? 1.時間復雜度

????????2.空間復雜度

? ? ? ? 不知道你們有沒有發現一個現象,或者看到這里想起來一些東西。在c語言的遞歸中,比如斐波那契數列,階乘遞歸,一開始數字小還好,但當你輸出一個較大的數字,斐波那契數列的第40,45,50,越往后計算機算的就越慢,而且打開任務管理器觀察,運行該程序所占用的內存百分比會只多不少。?我以斐波那契數列來實測一下。

#include<stdio.h>int Fib(int n)
{if (2>=n){return 1;}else{return Fib(n - 2) + Fib(n - 1);}
}
int main()
{int a = 0;scanf("%d",&a);int ret =Fib(a);printf("%d\n",ret);return 0;}

? ? ? ?輸入的值為30時:速度很快,瞬間出來。

時間復雜實測

? ? ? ?輸入值為40時:?出來了,過了5秒,光標在閃動(由于博主嘗試錄屏,但是無法錄制到cmd框,就不能放出視頻演示了,手機錄制效果不好,大家自行嘗試)

????????

? ? ? ? ?輸入的值為45時,大概過了半分鐘,才出結果,數字也確實非常大。

?????????說明用遞歸這個算法來解決斐波那契數列,數字大了,并不好,用for循環,會更好。計算時間就表示時間復雜度,內存資源的消耗就表示空間復雜度。那也不能每次都上機實測,所以就有了這兩個概念。

3.時間復雜度

? ? ? 3.1 時間復雜度的概念

????????算法的時間復雜度是程序基本操作的執行次數,就是一個基本表達式,它在程序中運行了多少次,引入一個案例來講:

void Func1(int N)
{
int count = 0;
for (int i = 0; i < N ; ++ i)
{for (int j = 0; j < N ; ++ j){count++;}
}for (int k = 0; k < 2 * N ; ++ k){count++;}int A = 10;while (A--){count++;}

? ? ? ? 上述過程中,在第一個for循環中,嵌套了一個for循環,那么在里面的執行次數,以未知數x來表示,就是,第三個for循環是單獨的,是2,第三個就是常數10了,總次數是,但是真心要算出來嗎,未知數小還好,x=1001,2345,54233這些復雜的數字,算起來未免過于繁瑣。 實際中我們計算時間復雜度時,我們其實并不一定要計算精確的執行次數,而只需要大概執行次數。那么這里我們使用大O的漸進表示法。

3.2 大O的漸進表示法 O()

????????在我的筆記中是這樣的記載的:

  1. 用常數1取代運行時間中的加法常數
  2. 保留最高階項即可
  3. 最高階次方不是1的話,把這個項的相乘系數刪了。

????????所以上面的表達式去掉常數,去掉非最高階,就剩個了,那么規范的糾正我的錯誤,我剛剛是用數學表達式來寫,正確的應該是把x換成N,所以是

????????通過上面大O的漸進表示法去掉了那些對結果影響不大的項,表示出了執行次數。另外有些算法的時間復雜度存在最好、平均和最壞情況:你選擇哪個?

????????這里舉個生活中的例子就明白了,你和你最好的朋友聚餐,或者工作有個重要的客戶要約見,然而你手中的活還沒干完,對方給你了下午5點,晚上7點和8點見面,你會選擇什么時間。按理來說容錯率最高的是8點吧,5點,萬一還沒忙完呢,7點,萬一堵車呢,最遲的時間應該是最好的。你提前到了,那給人印象很好,卡點是正常,遲到就給人不好印象了。這就是最好,折中和最壞預期結果。為了心理預期,我們往往會選擇最遲的點。這樣很好理解了吧

? ? ? ? 在算法中,在一個長度為N數組中搜索一個數據x:

最好情況:1次找到

最壞情況:N次找到

平均情況:N/2次找到

時間復雜度應該是

4.空間復雜度

? ? ? ? 空間復雜度也是數學表達式,是算法在運行過程中占用內存空間大小的多少,但是說實話真去測算消耗了多少空間?不,算的是變量的個數,也是大O的漸進表示法 O(),依舊舉個例子說明,用斐波那契數列來舉例子:

#include<stdio.h>int Fib(int n)
{if (2>=n){return 1;}else{return Fib(n - 2) + Fib(n - 1);}
}

? ? ? ? 計算有幾個變量,也就是開辟了幾個空間,由于n是不知道的,所以開辟了n個空間,空間復雜度為

5. 常見的時間復雜度和空間復雜度計算

5.1 時間復雜度計算

? ? ? ? 例1:

void Func2(int N)
{int count = 0;for (int k = 0; k < 2 * N ; ++ k){++count;}int M = 10;while (M--){++count;}printf("%d\n", count);
}

? ? ? ? 例2:

void Func3(int N, int M)
{int count = 0;for (int k = 0; k < M; ++ k){++count;}for (int k = 0; k < N ; ++ k){++count;}printf("%d\n", count);
}

? ? ? ? 例3:冒泡排序

void BubbleSort(int* a, int n)
{assert(a);for (size_t end = n; end > 0; --end){int exchange = 0;for (size_t i = 1; i < end; ++i){if (a[i-1] > a[i]){Swap(&a[i-1], &a[i]);exchange = 1;}}if (exchange == 0)break;}
}

? ? ? ? 例4:二分查找

int BinarySearch(int* a, int n, int x)
{assert(a);int begin = 0;int end = n-1;while (begin < end){int mid = begin + ((end-begin)>>1);if (a[mid] < x)begin = mid+1;else if (a[mid] > x)end = mid;elsereturn mid;}return -1;
}

? ? ? ? 例5:階乘遞歸

long long Fac(size_t N)
{if(0 == N)return 1;return Fac(N-1)*N;
}

? ? ? ? 例6:斐波那契數列

long long Fib(size_t N)
{if(N < 3)return 1;return Fib(N-1) + Fib(N-2);
}

? ? ? ? 案例分析:


  1. 案例1,是2N+M,根據大O的漸進表示法,M是個常數,所以是
  2. 案例2,是M+N次,根據大O的漸進表示法,M,N都是未知的,所以是
  3. 案例3,其實是個冒泡排序,最好的情況就是它是個有序數組,比如{1,2,3,4,5,6.....,n},那么就只要排n-1次,最壞的情況,就是完全無序,第一趟排,n-1次,第二趟,n-2次,最后一趟,1次。總次數加起來就是(n-1)+(n-2)+(n-3)+.....+1,總和為,所以按最壞的打算時間復雜度O(N^2)
  4. 案例4,是個二分查找,最好1次,最壞O(logN)次,時間復雜度為 O(logN) ,logN在算法分析中表示是底數為2,對數為N。ps:二分查找的原理就是縮小一半查找,理想中很好很厲害,但現實中不可靠,因為只適用于有序數組。
  5. 階乘算法,最好是1次,最壞是N次,時間復雜度為O(N)。
  6. 斐波那契數列,操作了2^N次,所以時間復雜度為O(2^N)。圖解如下:

    ?

????????不畫圖是很難看出來的,1生2,2生4,4生8,每一個誕生2個函數要執行 ,所以說畫圖很重要,不畫圖心里是很難憑空心算的。實踐出真知

5.2 空間復雜度計算

? ? ? ? 例1:冒泡排序

void BubbleSort(int* a, int n)
{assert(a);for (size_t end = n; end > 0; --end){int exchange = 0;for (size_t i = 1; i < end; ++i){if (a[i-1] > a[i]){Swap(&a[i-1], &a[i]);exchange = 1;}}if (exchange == 0)break;}
}

? ? ? ? 例2:階乘遞歸

long long Fac(size_t N)
{if(N == 0)return 1;return Fac(N-1)*N;
}

????????例3 :斐波那契數列

long long Fib(size_t N)
{if(N < 3)return 1;return Fib(N-1) + Fib(N-2);
}

案例分析:


  1. 例1冒泡排序函數內部,看看開辟了幾個變量,數變量就好了,end,exchange,i,三個,是常數,所以空間復雜度為O(1);
  2. 例2遞歸調用了N次,開辟了N個棧幀,每個棧幀又會開辟另一個空間,而遞歸不結束,空間不歸還,所以產生了FAC(N),FAC(N-1),FAC(N-2)........FAC(1),FAC(0)。這是個嵌套調用!!!,沒有銷毀掉,所以空間復雜度為O(N),不要以為單個棧幀空間里的變量只有一個N,沒有別的變量,你要算N個空間里的變量數量。
  3. 例3是1分為2,然后2里面的兩個遞歸用的同一塊空間,是先調用n,然后調用n-1,一直調用到末尾2,符合if條件,返回了!注意開始歸了!2的上一層是3,3下面的2已經調用了,所以會調用另一邊1,1調用了,再返回3。然后發現3的1和2都計算過了,往上返回到4,依次往上,因為遞歸的過程是先遞后歸,遞一邊,遞完返回再歸另外一邊,空間復雜度為O(N),這個案例注意調試,我是調試了很多次,看了很多次N的變化,畫了遞歸流程圖,才看明白,其實講的再多,不如自己去好好的認真調試一遍,就很nice。

    ?

階乘遞歸空間復雜度

?

?

6.時間復雜度對比圖

? ? ? ? 這是我從網絡上找的兩張關于時間復雜度隨著個數的增大的對比圖,(logn理想狀態是很好的)其實時間復雜度要比空間復雜度復雜很多,空間復雜度大多都是O(1),O(N),而時間復雜度會多很多,大家也可以網上找找,大部分圖都是一樣的。

時間復雜度

?????????再者就是常見的時間復雜度參數了

7.結語

????????本篇文章作為數據結構的開篇,就先講這么多,時間復雜度和空間復雜度是貫穿整個數據結構的,另外后面的內容順序表,鏈表等都涉及到動態開辟空間,所以C語言中的動態內存管理以及函數棧幀空間的學習是很必要的,因為順序表,和棧都和通訊錄的撰寫邏輯有關聯。記住一開始說的三點,畫圖,調試,?了解函數棧幀空間?It is imperative?for you?to learn!共同進步,就像gitee里說的,希望你的代碼有朝一日能夠像下面那張圖片一樣。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/74386.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/74386.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/74386.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

node-ddk,electron,截屏封裝(js-web-screen-shot)

node-ddk 截屏封裝(js-web-screen-shot) https://blog.csdn.net/eli960/article/details/146207062 也可以下載demo直接演示 http://linuxmail.cn/go#node-ddk 感謝/第三方 本截屏工具, 使用的是: js-web-screen-shot https://www.npmjs.com/package/vue-web-screen-shot…

泰坦軍團攜手順網旗下電競連鎖品牌樹呆熊 共創電競新紀元

在電競行業的浪潮中&#xff0c;品牌之間的戰略合作愈發成為推動市場前行的重要動力。最近&#xff0c;電競顯示器領域領軍品牌泰坦軍團高層領導出席順網旗下電競連鎖品牌樹呆熊十周年盛典。會議現場&#xff0c;雙方高層領導宣布泰坦軍團與樹呆熊正式達成戰略合作伙伴關系。 在…

HandyJSON原理

HandyJSON 的優勢 JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式, 應用廣泛. 在 App 的使用過程中, 服務端給移動端發送的大部分都是 JSON 數據, 移動端需要解析數據才能做進一步的處理. 在解析JSON數據這一塊, 目前 Swift 中流行的框架基本上是 SwiftyJSON, …

信號的產生和保存

信號的產生 信號就是操作系統對用戶操作做出的反應&#xff0c;但它的本質就是往操作系統寫入信號&#xff0c;這是由操作系統的結構決定的。通過修改比特位來告訴操作系統接收信號和傳了幾號信號。 也正是因為我們身為用戶無法親自修改內核數據&#xff0c;所以我們需要通過操…

在C++ Qt中集成Halcon窗口并實現跨平臺兼容和大圖加載

目錄 1. Halcon窗口嵌入Qt Widget 2. 處理大圖加載 3. 多線程優化顯示 4. 跨平臺兼容性 1. Halcon窗口嵌入Qt Widget 將Halcon的HWindow控件嵌入到Qt的QWidget容器中,利用系統原生句柄實現跨平臺。 #include <HalconCpp.h> #include <QWidget>class HalconWi…

深度學習技術與應用的未來展望:從基礎理論到實際實現

深度學習作為人工智能領域的核心技術之一&#xff0c;近年來引起了極大的關注。它不僅在學術界帶來了革命性的進展&#xff0c;也在工業界展現出了廣泛的應用前景。從圖像識別到自然語言處理&#xff0c;再到強化學習和生成對抗網絡&#xff08;GAN&#xff09;&#xff0c;深度…

藍光三維掃描技術:汽車零部件檢測的精準高效之選

——汽車方向盤配件、保險杠塑料件、鈑金件檢測項目 汽車制造工業的蓬勃發展&#xff0c;離不開強大的零部件制造體系作支撐。汽車零部件作為汽車工業的基礎&#xff0c;其設計水平、制造工藝、質量控制手段逐漸與國際標準接軌&#xff0c;對于零部件面差、孔位、圓角、特征線…

數據庫聯表Sql語句建一個新表(MySQL,Postgresql,SQL server)

數據庫聯表Sql語句建一個新表(MySQL,Postgresql,SQL server) 如果你想基于 SELECT USERS.ID,USERS.NAME,USERS.EMAIL,USERS.ID_CARD,USERS.V_CARD,USERS.ADDRESS,v_card.type,v_card.amount FROM USERS JOIN v_card on USERS.V_CARDv_card.v_card 這個查詢結果創建一個新表&am…

六十天前端強化訓練之第三十天之深入解析Vue3電商項目:TechStore全棧實踐(文結尾附有源代碼)

歡迎來到編程星辰海的博客講解 看完可以給一個免費的三連嗎&#xff0c;謝謝大佬&#xff01; 目錄 深入解析Vue3電商項目&#xff1a;TechStore全棧實踐 一、項目架構設計 二、核心功能實現 三、組合式API深度實踐 四、性能優化實踐 五、項目擴展方向 六、開發經驗總結…

【人工智能】機器學習中的評價指標

機器學習中的評價指標 在機器學習中&#xff0c;評估指標&#xff08;Evaluation Metrics&#xff09;是衡量模型性能的工具。選擇合適的評估指標能夠幫助我們更好地理解模型的效果以及它在實際應用中的表現。 一般來說&#xff0c;評估指標主要分為三大類&#xff1a;分類、…

不同機床對螺桿支撐座的要求有哪些不同?

螺桿支撐座是機械設備中重要的支撐部件&#xff0c;其選擇直接影響到設備的穩定性和使用壽命&#xff0c;尤其是在機床中&#xff0c;不同的機床對螺桿支撐座的要求也是不同的。 1、精度&#xff1a;精密測量用的基準平面和精密機床機械的檢驗測量設備&#xff0c;需要使用高精…

在Spring Boot中,可以通過實現一些特定的接口來拓展Starter

在Spring Boot中&#xff0c;開發者可以通過實現一些特定的接口來拓展Starter。這些接口允許開發者自定義Spring Boot應用程序的配置和行為&#xff0c;從而創建功能豐富且易于使用的Starter。以下是一些關鍵的接口&#xff0c;用于拓展Starter&#xff1a; EnvironmentPostPro…

深入理解 tree 命令行工具:目錄結構可視化的利器

文章目錄 前言1. 什么是 tree 命令&#xff1f;安裝 tree 2. tree 的基本用法顯示當前目錄的樹狀結構顯示指定目錄的樹狀結構 3. tree 的常用選項3.1 顯示隱藏文件3.2 排除特定目錄或文件3.3 限制遞歸深度3.4 顯示文件大小3.5 顯示文件的權限信息3.6 將輸出保存到文件 4. 實際應…

Federated learning client selection algorithm based on gradient similarity閱讀

基于梯度相似性的聯邦學習客戶端選擇算法 Abstract 摘要introduction**背景****目的****結論****結果****討論****思路** 鏈接&#xff1a;https://link.springer.com/article/10.1007/s10586-024-04846-0 三區 Abstract 摘要 聯邦學習&#xff08;FL&#xff09;是一種創新的…

【測試工具】如何使用 burp pro 自定義一個攔截器插件

在 Burp Suite 中&#xff0c;你可以使用 Burp Extender 編寫自定義攔截器插件&#xff0c;以攔截并修改 HTTP 請求或響應。Burp Suite 支持 Java 和 Python (Jython) 作為擴展開發語言。以下是一個完整的流程&#xff0c;介紹如何創建一個 Burp 插件來攔截請求并進行自定義處理…

網絡編程的概念&作用

網絡編程是什么&#xff1f; 想象一下&#xff0c;你和朋友在不同的房間里&#xff0c;你們想互相傳遞紙條聊天。網絡編程就像是編寫一套規則&#xff0c;讓計算機能夠通過網絡&#xff08;比如互聯網&#xff09;互相傳遞信息。這些信息可以是文字、圖片、視頻&#xff0c;甚…

航天軍工與金融行業 UE/UI 設計:跨越領域的體驗革新之道

在數字化時代&#xff0c;用戶體驗&#xff08;UE&#xff09;和用戶界面&#xff08;UI&#xff09;設計成為眾多行業提升競爭力的關鍵因素。航天軍工與金融行業雖業務性質差異巨大&#xff0c;但在 UE/UI 設計方面卻面臨著一些相似挑戰&#xff0c;同時也在各自的探索中展現出…

【Git】--- 分支管理

Welcome to 9ilks Code World (??? ? ???) 個人主頁: 9ilk (??? ? ???) 文章專欄&#xff1a; Git 本篇博客我們來介紹Git的一個重要功能之一 ---- 分支。我們將講解關于分支的各種操作&#xff0c;以及如何幫助我們進行開發。 &#x1f3e0; 理解分支…

純血鴻蒙:中國操作系統自主創新的里程碑

引言&#xff1a;破局者登場 2024 年 10 月&#xff0c;搭載純血鴻蒙操作系統&#xff08;HarmonyOS NEXT&#xff09;的華為 Mate 70 系列正式發布&#xff0c;首日預約量突破 330 萬。這場現象級熱度的背后&#xff0c;不僅是消費者對硬件創新的期待&#xff0c;更是中國科技…

二造考試的備考過程中如何保持良好的心態?

在二級造價師考試的備考過程中&#xff0c;保持良好的心態至關重要&#xff0c;以下是一些有效的方法&#xff1a; 樹立正確的考試觀念 )認識到二級造價師考試是職業生涯中的一個重要環節&#xff0c;但不是唯一的決定因素。把它看作是提升自己專業能力、豐富知識儲備的機會&am…