1. 程式人生 > >《資料結構與演算法分析-C語言描述》詳解-Sec2(一)

《資料結構與演算法分析-C語言描述》詳解-Sec2(一)

第二章為“演算法分析”,該部分主要介紹了電腦科學中目前用於測量一個演算法的運行復雜的具體數學方法;同時給出了多個問題示例,對每個問題分別採用不同複雜度的演算法,可以直觀地瞭解到在解決實際問題時,不僅僅需要能夠得出結果的演算法,更應該給出演算法複雜度更低的演算法的意義

  • 數學工具:“大O”表示法,用於估計一個程式執行所需要的時間
  • 問題示例:採用更優的演算法,使得解決問題所需要的時間縮短几個量級
  • 遞迴函式:舉例說明不良的遞迴導致演算法所複雜度極高

數學基礎

  • 定義1:若c>0,n0>0使得當Nn0T(N)cf(N),則記為T(N)=O(f(N))
  • 定義2:若c>
    0,n0>0
    使得當Nn0T(N)cf(N),則記為T(N)=Ω(f(N))
  • 定義3:T(N)=Θ(h(N)), 當且僅當T(N)=O(h(N))T(N)=Ω(h(N))
  • 定義4:T(N)=o(h(N)), 當且僅當T(N)=O(h(N))T(N)Θ(h(N))

以上四個定義中用於建立不同函式間執行時間的相對級別,稱為大O描述法。其中T(N)為函式的執行時間,N為運算的規模,如迴圈的次數,陣列大小等等。比較兩個函式在某個N下的實際執行時間值的絕對值的意義是不大的,因為程式執行的時間會受到很多特殊因素的影響,如迴圈中判斷是否應跳出迴圈,一個大的運算每次附帶的一個單次運算,這些特殊因素在N較大時對T(N)幾乎沒有影響,但在N較少時可能會佔據 較大比例;而且很多情況下程式會走向不同的分支,其執行時間是不一致的,也很難精確統計其執行時間。

大O描述則提供了一種反映函式計算時間的增長率的方法,其定義用極限可以表示為:若T(N)=O(f(N)), 則

limn+T(N)f(N)=X
其中X為0或者常數,從直觀的角度可以理解為當N很大時,T(N)比f(N)數量級相等或更小。

有一點需要注意的是,若T(N)=N,則T(N)=O(N^2)和T(N)=O(N)均是成立的,但很顯然只有後者是有意義的,因為O()包含了一個“大於等於”的含義,因此實際中是需要儘可能找到數量級相等的情況,換句話說,應該找到T(N)=Θ(h(N)),使用大O一方面是因為慣例,另外一方面是因為很多時候我們不能確定得到的h(N)是和T(N)等數量級的而只能確定其數量不會超過h(N)

大O分析基礎

計算模型

  • 指令時長:實際計算機在執行不同指令的時間是很不一樣的,如執行乘法運算和執行賦值操作就會相差好幾倍,因此大O分析中假設計算機中只有少數幾個基本操作如加減乘除,且所有這些基本操作耗時是相等的,由於這些基本操作實際執行時間相差一般不會超過O(1),所以這個假設對於N很大時是可以接受的
  • 記憶體和變數範圍:認為計算時記憶體是無限大,因此不需要考慮缺頁中斷等額外消耗的時間,同時設定各種變數是有固定長度,如int型為32位,這是為了防止某些運算可以潛在地通過並行方式減少計算時間的可能,如假設int有64位,則理論上可以同時對兩組32位整數進行相加。

大O估算公式

對於大O估算而言基本公式有兩個,若T1(N)=O(f(N)),T2(N)=O(g(N))則:

  • T1(N)+T2(N)=max(O(f(N)),O(g(N)))
  • T1(N)T2(N)=O(f(N)g(N))

而對於大多數程式函式而言,其可能的複雜度形式有以下幾種:

複雜度 名稱
c 常數級
logN 對數級
log2N 對數平方級
N 線性級
NlogN 對數線性級
N2 平方級
N3 立方級
2N 指數級

其中複雜度從上到下依次遞增,對於實際可用的程式而言指數級往往是不可接受的,計算機實際能解決的問題目前只限於多項式複雜度以下,即O(Nk)複雜度以下,這些能用多項式複雜度解決的問題稱為P問題(Polynomial),不確定是否能找到多項式複雜度解法的問題稱為NP問題(Nondeterministic Polynomial),而研究NP問題是否存在P演算法則是電腦科學的一個非常重要的研究方向,因為現實中大多數問題均是NP問題。
而對於以上這些常見覆雜度形式又有以下兩個經驗公式可以用於進行復雜度的比較:

  • 若T(N)為一個N次多項式,則T(N)=Θ(Nk)`
  • kR,logkN=O(N),即log函式增長是非常緩慢的

以上是書上給出的公式,同時我自己在解題時也發現了一些沒有經過嚴格證明的經驗公式,大家可以參考:

  • kR,k>0;logN=O(Nk)
  • k1,k2R,k1,k2>0;logk1N=O(Nk2)

此外一個關於調和級數的求和公式也常常用到:

相關推薦

資料結構演算法分析-C語言描述 3.4 交集

題目:給定兩個已排序的表L1和L2,只使用基本的表操作編寫計算L1∩L2的過程 /* 3.4 交集 思路:由於是已排序,遍歷L的同時,將L的資料和P的資料進行比較, 如果相同則輸出,並因為是交集,不需要相同,所以P = P->next; 如果不相同,則L = L->nex

資料結構演算法分析——C語言描述3.3

通過只調整指標(而不是資料)來交換兩個相鄰的元素 //3.3 a.單鏈表 void OneListSwapByAdd(ElemType B, ElemType C, List L) { Position a_pos, b_pos, c_pos; b_pos = Find(B, L);

資料結構演算法分析-C語言描述 3.2

資料結構與演算法分析-C語言描述 3.2  PrintLots #include "stdafx.h" #include"List.h" int main() { List L, P; L = CreatedList(); P = CreatedList(); Print

資料結構演算法分析c語言描述Mark Allen--佇列ADT連結串列實現

佇列ADT連結串列實現 使用連結串列儲存 操作集合 入隊 出隊 初始化 返回隊前元素 列印 #include <stdio.h> #includ

資料結構演算法分析c語言描述Mark Allen--迴圈佇列ADT陣列實現

迴圈佇列ADT陣列實現 使用陣列儲存 操作集合 入隊 出隊 清空 初始化 返回隊前元素 列印 重點注意! 對於一個迴圈佇列 front == rear時候佇列

資料結構演算法分析c語言描述Mark Allen--線性錶鏈表方法實現

線性表--連結串列實現 標頭檔案 #define ElementType int #define INF INT_MAX #ifndef _List_H struct Node; typedef struct Node *PtrToNode; typedef PtrToN

資料結構演算法分析c語言描述Mark Allen--多項式ADT陣列實現

多項式ADT陣列實現 使用陣列進行儲存 操作集合 乘法 加法 標頭檔案 //cpp head file PloynomialADTarray.h #define MaxDegree 1000 typedef struct Pol { int C

資料結構演算法分析c語言描述Mark Allen--多項式ADT連結串列實現

多項式ADT連結串列實現 使用連結串列結構儲存 操作集合 多項式加法 多項式乘法 多項式的顯示 標頭檔案 //標頭檔案 typedef struct Node *PtrToNode; struct Node { int Cofficient

資料結構演算法分析C語言描述》pdf

《資料結構與演算法分析:C語言描述(原書第2版)》內容簡介:書中詳細介紹了當前流行的論題和新的變化,討論了演算法設計技巧,並在研究演算法的效能、效率以及對執行時間分析的基礎上考查了一些高階資料結構,從歷史的角度和近年的進展對資料結構的活躍領域進行了簡要的概括。

資料結構演算法分析c語言描述Mark Allen--棧ADT陣列實現

棧ADT陣列實現 使用陣列儲存 操作集合 入棧push 出棧pop 清空 初始化 返回棧頂元素 得到一個隨機棧 列印整個棧 #include <stdio.h> #include <stdlib.h> #include <

資料結構演算法分析-c語言描述》第三章表ADT程式碼補全

這本書講的很不錯(英文版)也讓我第一次懷疑了自己是否是中國人,翻譯啊真的有時候看不懂有時還要看英文版的才能看懂這個意思而且書上的程式碼給的不全故放部落格上給自己複習和造福大眾(???) #include<stdio.h> #include<stdlib.h

資料結構演算法分析——C語言描述

第一章:引論 第k大問題 第一種方法,先進行排序,再返回位置k上的元素。(簡單排序問題) 第二種方法,先將前k個元素讀入,再將剩下的元素逐個讀入,如果新元素大於陣列中第k個元素就找到他合適的位置並將陣列中的一個元素擠出。 第三種方法,利用快排的特點(假設預設升序

C語言實現摘自資料結構演算法分析 C語言描述

一、概述: 棧(stack)是限制插入和刪除只能在一個位置上進行的表,該位置是表的末端,叫做棧的頂(top)。對棧的基本操作有Push(進棧)和Pop(出棧),前者相當於插入,後者則是刪除最後插入的元素。 棧有時又叫做LIFO(後進先出)表。在圖1中描述的模型只象徵著Pus

資料結構演算法分析C語言描述----Makefile

TAR = main OBJ = stack.o main.o $(TAR) : $(OBJ)gcc -o [email protected] $^ %.o: %.cgcc $(CFLAGS) -c $< clean:rm $(TAR) $(OBJ)

資料結構演算法分析c語言描述Mark Allen--棧ADT連結串列實現

棧ADT連結串列實現 使用連結串列儲存 操作集合 入棧push 出棧pop 清空 初始化 返回棧頂元素 列印整個棧 #include <stdio.h> #include <time.h> #include <stdli

資料結構演算法分析-C語言描述-Sec2

第二章為“演算法分析”,該部分主要介紹了電腦科學中目前用於測量一個演算法的運行復雜的具體數學方法;同時給出了多個問題示例,對每個問題分別採用不同複雜度的演算法,可以直觀地瞭解到在解決實際問題時,不僅僅需要能夠得出結果的演算法,更應該給出演算法複雜度更低的演

資料結構演算法分析java語言描述》知識點總結(3-4章)

3. 表、棧、佇列 3.1 抽象資料型別(ADT) 表的一些簡單操作可以通過使用陣列來完成,如果發生對錶的一些插入和刪除操作,特別是對錶的前端進行,那麼陣列就不是一種很好的選擇了,就需要使用連結串列

資料結構演算法分析:Java語言描述(第2版)》電子書下載 -百度網盤 高清版PDF格式

     作者:韋斯 (Mark Allen Weiss) 馮舜璽 (譯) 出版日期:2009年1月1日 出版社:機械工業出版社 頁數:400頁 ISBN:9787111231837 檔案格式:PDF 檔案大小:15.95 MB

資料結構演算法分析java語言描述》學習筆記二

一、抽象資料型別  抽象資料型別(abstract data type,ADT)是帶有一組操作的一些物件的集合。 二、ArrayList 的實現 自定義ArrayList 實現程式碼如下: package com.caitang.mjq; import java.uti

資料結構演算法分析—Java語言描述》pdf

下載地址:網盤下載 內容簡介 編輯 “資料結構”是計算機專業的基礎與核心課程之一,Java是現今一種熱門的語言。本書在編寫過程中特別考慮到了面向物件程式設計(OOP)的思想與Java語言的特性。它不是從基於另一種程式設計語言的資料結構教材簡單地“改編”而來