心智圖資源庫 資料結構(2)
資料結構(的三要素是:邏輯結構、物理結構(儲存結構)、資料的運算,歡迎一起來看資料結構知識。
編輯於2023-05-28 15:46:20이것은 (III) 저산소증-유도 인자 프롤릴 하이드 록 실라 제 억제제에 대한 마인드 맵이며, 주요 함량은 다음을 포함한다 : 저산소증-유도 인자 프롤릴 하이드 록 실라 제 억제제 (HIF-PHI)는 신장 빈혈의 치료를위한 새로운 소형 분자 경구 약물이다. 1. HIF-PHI 복용량 선택 및 조정. Rosalasstat의 초기 용량, 2. HIF-PHI 사용 중 모니터링, 3. 부작용 및 예방 조치.
이것은 Kuka Industrial Robots의 개발 및 Kuka Industrial Robot의 모션 제어 지침에 대한 마인드 맵입니다. 주요 내용에는 쿠카 산업 로봇의 역사, 쿠카 산업 로봇의 특성, 쿠카 산업 로봇의 응용 분야, 2. 포장 프로세스에서 쿠카 로봇은 빠르고 일관된 포장 작업을 달성하고 포장 효율성을 높이며 인건비를 줄입니다. 2. 인건비 감소 : 자동화는 운영자에 대한 의존성을 줄입니다. 3. 조립 품질 향상 : 정확한 제어는 인간 오류를 줄입니다.
408 컴퓨터 네트워크가 너무 어렵습니까? 두려워하지 마세요! 나는 피를 구토하고 지식 맥락을 명확히하는 데 도움이되는 매우 실용적인 마인드 맵을 분류했습니다. 컨텐츠는 매우 완전합니다. 네트워크 아키텍처에서 응용 프로그램 계층, TCP/IP 프로토콜, 서브넷 디비전 및 기타 핵심 포인트에 이르기까지 원칙을 철저히 이해하는 데 도움이 될 수 있습니다. 📈 명확한 논리 : Mindmas 보물, 당신은 드문 기회가 있습니다. 서둘러! 이 마인드 맵을 사용하여 408 컴퓨터 네트워크의 학습 경로에서 바람과 파도를 타고 성공적으로 해변을 얻으십시오! 도움이 필요한 친구들과 공유해야합니다!
이것은 (III) 저산소증-유도 인자 프롤릴 하이드 록 실라 제 억제제에 대한 마인드 맵이며, 주요 함량은 다음을 포함한다 : 저산소증-유도 인자 프롤릴 하이드 록 실라 제 억제제 (HIF-PHI)는 신장 빈혈의 치료를위한 새로운 소형 분자 경구 약물이다. 1. HIF-PHI 복용량 선택 및 조정. Rosalasstat의 초기 용량, 2. HIF-PHI 사용 중 모니터링, 3. 부작용 및 예방 조치.
이것은 Kuka Industrial Robots의 개발 및 Kuka Industrial Robot의 모션 제어 지침에 대한 마인드 맵입니다. 주요 내용에는 쿠카 산업 로봇의 역사, 쿠카 산업 로봇의 특성, 쿠카 산업 로봇의 응용 분야, 2. 포장 프로세스에서 쿠카 로봇은 빠르고 일관된 포장 작업을 달성하고 포장 효율성을 높이며 인건비를 줄입니다. 2. 인건비 감소 : 자동화는 운영자에 대한 의존성을 줄입니다. 3. 조립 품질 향상 : 정확한 제어는 인간 오류를 줄입니다.
408 컴퓨터 네트워크가 너무 어렵습니까? 두려워하지 마세요! 나는 피를 구토하고 지식 맥락을 명확히하는 데 도움이되는 매우 실용적인 마인드 맵을 분류했습니다. 컨텐츠는 매우 완전합니다. 네트워크 아키텍처에서 응용 프로그램 계층, TCP/IP 프로토콜, 서브넷 디비전 및 기타 핵심 포인트에 이르기까지 원칙을 철저히 이해하는 데 도움이 될 수 있습니다. 📈 명확한 논리 : Mindmas 보물, 당신은 드문 기회가 있습니다. 서둘러! 이 마인드 맵을 사용하여 408 컴퓨터 네트워크의 학습 경로에서 바람과 파도를 타고 성공적으로 해변을 얻으십시오! 도움이 필요한 친구들과 공유해야합니다!
資料結構
1.1資料結構的基本概念
資料結構
基本概念
數據
資料元素、資料項
資料對象、資料結構
資料型別、抽象資料型態(ADT)
三要素
邏輯結構
物理結構(儲存結構)
數據的運算
1.2.1演算法的基本概念
演算法的基本概念
什麼是演算法
程式=資料結構 演算法
資料結構是要處理的訊息
演算法是處理資訊的步驟
演算法的五個特徵
演算法必須要具備的特性
有窮性
有窮時間內能執行完
演算法是有窮的
程序可以是無窮的
確定性
相同輸入只會產生相同輸出
可行性
可以用現有的基本操作實現演算法
輸入
丟給演算法處理的數據
輸出
演算法處理的結果
「好」演算法的特質
設計演算法時要盡量追求的目標
正確性
能正確解決問題
可讀性
演算法的描述要讓其他人看的懂
健壯性
演算法能處理一些異常狀況
高效率與低儲存量需求
即演算法執行省時、省內存
時間複雜度低、空間複雜度低
1.2.2演算法的時間複雜度
時間複雜度
如何計算
①找到一個基本操作(最深層循環)
②分析該基本運算的執行次數X和問題規模n的關係x=f(n)
③x的數量級O(x)就是演算法複雜度
常用技巧
加法規則
乘法規則
書上p6常對冪指階
三種複雜度
最壞時間複雜度:考慮輸入資料「最壞」的情況
平均時間複雜度:考慮所有輸入資料都等機率出現的情況
最好時間複雜度:考慮輸入資料「最好」的情況
空間複雜度
如何計算
普通程式
①找到所佔空間大小與問題規模相關的變數
②分析所佔空間x與問題規模n的關係x=f(n)
③x數量級O(x)是演算法空間複雜度S(n)
遞迴程式
①找到遞歸呼叫的深度x與問題規模n的關係x=f(n)
②x 數量級O(x)是演算法空間複雜度S(n)
註:有的演算法各層函數所需儲存空間不同,分析方法略有不同
常用技巧
加法規則
乘法規則
同時間複雜度
2.1線性表的定義和基本操作
線性表
定義
值的注意的特性
資料元素同類型、有限、有序
重要術語
表長、空表
表頭、表尾
前驅、後繼
資料元素的位元序(從1開始)
基本操作
創銷、增刪改查(所有資料結構適用的記憶思維)
判空、判長、列印輸出
其他值得注意的點
理解什麼時候要傳入參數的引用“&”
函數命名要有可讀性
儲存/物理結構
順序表(順序儲存)
定義(如何用程式碼實現)
基本操作的實現
鍊錶(鍊式儲存)
單鍊錶
定義(如何用程式碼實現)
基本操作的實現
雙鍊錶
循環鍊錶
靜態鍊錶
2.2.1順序表的定義
順序表
儲存結構
邏輯上相鄰的資料元素物理上也相鄰
實現方式
靜態分配
使用“靜態數組”實現
大小一旦確定就無法改變
動態分配
使用“動態數組”實現
L.data=(ElemType*)malloc(sizeof(ElemType)*size);
順序表存滿時,可再用malloc動態拓展順序表的最大容量
需要將資料元素複製到新的儲存區域,並用free函數釋放原始區域
特點
隨機訪問
能在O(1)時間內找到第i個元素
儲存密度高
拓展容量不方便
插入刪除資料元素不方便
2.2.2.1順序表的插入刪除
順序表的基本操作
插入
Listinsert(&L,i,e)
將元素e插入到L的第i個位置
插入位置之後的元素都要後移
時間複雜度
最好O(1)、最壞O(n)、平均O(n)
刪除
ListDelete(&L,i,&e)
將L的第i個元素刪除,並用e返回
刪除位置之後的元素要前移
時間複雜度
最好O(1)、最壞O(n)、平均O(n)
程式碼要點
程式碼中註意位序i和陣列下標的區別
演算法要有健壯性,注意判斷i的合法性
移動元素時,從前面的元素開始?還是從表尾元素開始?
分析程式碼,理解為什麼有的參數要加「&」引用
2.2.2.2順序表的查找
順序表的基本操作
按位查找
GetElem(L,i)
取得表L中第i個位置的元素的值
用數組下標即可得到第i個元素L.data【i—1】
時間複雜度
最好/最壞/平均時間複雜度都是O(1)
按值查找
LocativeElem(L,e)
在順序表L中尋找第一個元素值等於e的元素,並傳回其位元序
從第一個元素開始依序往後檢索
時間複雜度
最好O(1):目標元素在第一個位置
最好O(n):目標元素在最後一個位置
最好O(n):目標元素在每個位置的機率相同
2.3.1單鍊錶的定義
單鍊錶
用“鍊式存儲”(存儲結構)實現了“線性結構”(邏輯結構)
一個結點儲存一個資料元素
各結點間的先後關係以一個指針表示
用程式碼定義一個單鍊錶
兩種實現
不帶頭結點
空表判斷:L==NULL。寫程式碼不方便
帶頭結點
空表判斷:L→next==NULL。寫程式更方便
其他注意的點
typedef關鍵字的用法
LinkList等價於LNode* 前者強調這是鍊錶,後者強調這是結點 合適的地方用合適的名字,代碼可讀性高
2.3.2.1單鍊錶的插入刪除
插入
按位序插入
帶頭結點
不帶頭結點
指定結點的後插操作
指定結點的前插操作
刪除
按位序刪除
指定結點的刪除
2.3.2.2單鍊錶的查找
按位查找
注意與「順序表」對比
單鍊錶不具備「隨機存取」的特性,只能依序掃描
按值查找
求單鍊錶長度
key
三種基本操作的時間複雜度都是O(n)
如何寫循環掃描各個結點的程式碼邏輯
注意邊界條件的處理
2.3.2.3單鍊錶的建立
採用頭插法建立單鍊錶
採用尾插法建立單鍊錶
2.3.3雙鍊錶
初始化
頭部點的prior.next 都指向NULL
插入(後插)
注意新插入結點、前驅結點、後繼結點的指針修改
⚠️邊界狀況:新插入結點在最後一個位置,需特別處理
刪除(後插)
注意刪除結點的前驅結點、後繼結點的指標修改
⚠️邊界狀況:如果刪除結點是最後一個資料結點,需特別處理
遍歷
從一個給定結點開始,後向遍歷、前向遍歷的實現(循環的終止條件)
鍊錶不具備隨機存取特性,查找操作只能透過順序遍歷實現
2.3.4循環鍊錶
循環單鍊錶
空表f
非空表
循環雙鍊錶
空表
非空表
代碼問題
2.3.5靜態鍊錶
2.3.6順序表和鍊錶的比較
3.1.1棧的基本概念
堆疊
定義
一種操作受限的線性表,只能在堆疊頂部插入、刪除
特性:後進先出(LIFO)
名詞:棧頂、棧底、空棧
基本操作
創、銷
增、刪(元素 進棧、出棧,只能在棧頂操作
查(獲得棧頂元素,但不刪除)
判空
3.1.2棧的順序存儲實現
順序堆疊
順序存儲,用靜態數組實現,並需要記錄棧頂指針
基本操作
創刪改查
都是O(1)時間複雜度
兩種實現
初始化時top=1
入堆疊
S.data[ S.top]=x;
出棧
x=S.data[S.top--];
獲得棧頂元素
x=S.data[S.top];
棧空/棧滿條件是?
初始化時top=0
入堆疊
S.data[S.top ]=x;
出棧
x=S.data[--S.top];
獲得棧頂元素
x=S.data[S.top-1];
棧空/棧滿條件是?
共享堆疊
兩個堆疊共享同一片記憶體空間,兩個堆疊從兩邊往中間成長
初始化
0號棧棧頂指標初始時top0=-1;1號棧棧頂指標初始時TOP1=MaxSize;
堆疊滿條件
top0 1==top1
3.1.3棧的鍊式儲存實現
鏈堆疊
用鍊式儲存方式實作的棧
兩種實作方式
帶頭結點
不帶頭結點(建議)
重要基本操作
創(初始化)
增(進棧)
刪(出棧)
查(取得棧頂元素)
如何判空、判滿
3.2.1隊列的基本概念
定義
一種操作受限的線性表,只能在隊尾插入,在隊頭刪除
特性:先進先出
名詞:隊頭、隊尾、空隊列、隊頭元素、隊尾元素
基本操作
創、銷
增、刪除(入隊、出隊,只能在規定的一端進行)
查(獲得隊頭元素,但不刪除)
判空
3.2.2隊列的順序實現
實現思想
用靜態數組存放資料元素,設定隊頭隊尾(front/rear)指針
循環隊列:用模運算(取餘)將儲存空間在邏輯上變成“環狀”
Q.rear=(Q.rear 1)%MaxSize
重要考點
如何初始化、入隊、出隊
如何判空、判滿
如何計算佇列的長度
分析思路
決定front、rear指標的指向
①rear指向隊尾元素後一個位置
②rear指向隊尾元素
確定判空判滿的方法
a.犧牲一個儲存單元
b.增加size變數記錄佇列長度
c.增加tag=0/1用於標記最近一次操作是出隊/入隊
……
3.2.3隊列的鍊式實現
佇列
用鍊式儲存實作佇列
帶頭節點
不帶頭結點
基本操作
創(初始化)
增(入隊)
注意第一個元素入隊
刪除(出隊)
注意最後一個元素出隊
查(取得隊頭元素)
判空
判滿?不存在的
3.2.4雙端隊列
隊列的變種
雙端佇列
允許兩段插入,兩端刪除的佇列
輸入受限的雙端隊列
允許從兩端刪除、從一端插入的佇列
輸出受限的雙端隊列
允許從兩端插入、從另一端刪除的佇列
考點:對輸出序列合法性的判斷
在堆疊中合法的輸出序列,在雙端佇列必合法
3.3.1棧在括號匹配的應用
用棧實作括號匹配
依序掃描所有字符,遇到左括號入棧, 遇到右括號則彈出棧頂元素檢查是否匹配
匹配失敗情況
1左括號單身
2右括號單身
3左右括號不匹配
3.3.2.1棧在表達式求值中的應用(上)
表達式求值問題
概念
運算子、運算元、界限符(DIY概念:左操作數、右操作數)
三種表達式
中綴表達式
運算子在運算元中間
後綴表達式(逆波蘭式)
運算子在運算元後面
前綴表達式(波蘭式)
運算子在操作數前面
⚠️後綴表達式考點
中綴轉後綴
①依照「左優先」原則決定運算子的運算次序
②依照①中確定的次序,依序將各個運算子和與之相鄰的兩個操作數 按〈左操作數 右操作數 運算子〉的規則合體
後綴轉中綴
由左往右掃描,每遇到一個運算符,就將〈左操作數 右操作數 運算符〉 變成(左操作數 運算子 右操作數)的形式
計算
從左往右掃描,遇到操作數入棧,遇到運算子則彈出兩個棧頂元素運算後入棧 (注意:先彈出的是「右操作數」)
前綴表達式
中綴轉前綴
①依照「右優先」原則決定運算子的運算次序
②依照①中確定的次序,依序將各個運算子和與之相鄰的兩個操作數 按〈 運算子 左操作數 右操作數 〉的規則合體
計算
從右往左掃描,遇到操作數入棧,遇到運算子則彈出兩個棧頂元素運算後入棧 (注意:先彈出的是「左操作數」)
3.3.2.2棧在表達式求值中的應用
用棧實作中綴轉後綴表達式
初始化一個棧,用來保存暫時還不能確定運算順序的運算符
從左到右處理各個元素,直到最後。可能會遇到三種情況
①遇到操作數。直接加入後綴表達式
②遇到界限符。遇到「(」直接入棧;遇到「)」則依序彈出堆疊內運算子並加入 後綴表達式,直到彈出“(”為止。注意:“(”不加入後綴表達式
③遇到運算子。依序彈出堆疊中優先權高於或等於目前運算符的所有運算符, 並加入後綴表達式,若碰到「(」或棧空則停止。之後再把目前運算子入棧
依上述方法處理完所有字元後,將堆疊中剩餘運算子依序彈出,並加入後綴表達式
用棧實現後綴表達式的計算
①從左往右掃描下一個元素,直到處理完所有元素
②若掃描到操作數則壓入堆疊,並回到①;否則執行③
③若掃描到運算符,則彈出兩個棧頂元素,執行對應運算,運算結果壓回棧頂,回到①
用棧實作中綴表達式的計算
初始化兩個棧,操作數棧和運算符棧
若掃描到操作數,壓入操作數棧
若掃描至運算子或界限符,則依照「中綴轉後綴」相同的邏輯壓入運算子棧 (期間也會彈出運算符,每當彈出一個運算符時,就需要再彈出兩個操作數棧的棧頂元素並執行相應 運算,運算結果再壓回到操作數棧)
3.3.3棧在遞迴的應用
函數呼叫的特性:最後被呼叫的函數最先被執行結束(LIFO)
函數呼叫時,需要用一個「函數呼叫堆疊」來存儲
呼叫返回地址
實參
局部變數
遞歸呼叫時,函數呼叫棧可稱為“遞歸工作棧” 每進入一次遞歸,就將遞歸呼叫所需資訊壓入棧頂 每退出一層遞歸,就從棧頂彈出對應訊息
3.4特殊矩陣的壓縮存儲
對稱矩陣
特徵:對方陣中的任一個元素,有a(i,j)=a(i,j)
壓縮:只儲存主對角線 下三角區(或主對角線 上三角區)
三角矩陣
特性:上三角區全為常數(下三角矩陣);或下三角區全為常數(上三角矩陣)
壓縮:依行優先/列優先規則依序儲存非常量區域,並在最後一個位置存放常數c
三對角矩陣(帶狀矩陣)
特徵:當|i-j|>1時,有a(i,j)=0(1≤i,j≤n)
壓縮:依行優先/列優先規則依序儲存帶狀區域
稀疏矩陣
非零元素個數小於零元素個數
壓縮:只儲存非零元素
順序儲存:順序儲存三元組<行,列,值>
鍊式儲存:十字鍊錶法
4.1.1串的定義與基本操作
字串
定義
串,即字串(String)是由零個或多個字元組成的有限序列
術語:串長、空串、空格串、子串、主串、字元在主串中的位置、子串在主串中的位置
串vs線性表
字串的資料物件限定為字元集
串的基本操作大多以「子串」為操作對象
基本操作
index(S,T),定位操作,找到串T在主串S的位置
StrCompare(S,T):比較操作。若S>T,則傳回值>0;若S=T,則傳回值=0; 若S<T,則傳回值<0;
其他…
字符集編碼
每個字元在計算機中對應一個二進制數,比較字元的大小其實就是比較二進位數的大小
4.1.2串的儲存結構
順序存儲
靜態數組
動態數組
malloc free
鍊式儲存
可讓每個結點存多個字符,沒有字符的位置用"#"或'/0' 補足
王道教材採用 —靜態數組
基本操作的實現
求子字串:bool SubString(SString&Sub,SString S,int pos,int len)
串的比較:int StringCompare(SString S,SString T)
求串在主串中的位置:int index(SString S,SString T)
4.2.1樸素模式匹配演算法
演算法思想
主串長度n,模式串長度m
將主串中所有長度為m的子串與模式串對比
找到第一個與模式串相符的子字串,並返回子串起始位置
若所有子字串都不匹配,則返回為零
最壞時間複雜度=O(nm)
4.2.2KMP演算法
5.1.1和5.1.2樹的定義和基本術語
基本概念
結點,邊,根節點,葉節點,分支結點,子樹
基本術語
節點之間的關係
父節點(雙親節點)、孩子結點
祖先結點,子孫結點
兄弟結點,堂兄弟結點
結點之間的路徑—只能從上往下
路徑長度—路徑上經過多少邊
結點,樹的屬性
結點的層次(深度),結點的高度
樹的深度(高度)
結點的度
結點的分支數
樹的度
樹中各結點的度數的最大值
有序樹vs無序樹
邏輯上看,各子樹是否有序,位置是否可互換
森林
由M個(M>0)個互不相交的樹組成森林
5.1.3樹的性質
考點一
結點數=總度數 1
考點二
度為m的樹
至少有一個結點度=m
一定是非空樹
m叉樹
允許所有結點的度數都<m
可以是空樹
考點三
度為m的樹第i層至多有幾個結點?
考點四
高度為h的m二元樹至多有幾個結點?
考點五
高度為h的m叉樹至少有幾個結點
高度為h,度為m的樹至少有幾個結點?
考點六
具有n個結點的m叉樹的最小高度為?
5.2.1.1二元樹的定義和基本術語
二元樹
基本概念
可為空二元樹
任意結點的度≤2
是有序樹,左子樹、右子樹不可顛倒
思考:二元樹vs度為2的有序樹
特殊二元樹
滿叉樹
高度為h,含有2×h-1個結點的二元樹
完全二元樹
在滿二元樹的基礎上可去掉若干個編號更大的結點
二元排序樹
左子樹關鍵字<根節點關鍵字<右子樹關鍵字
平衡二元樹
左右子樹深度差不超過1
5.2.1.2二元樹的性質
5.2.2二元樹的儲存結構
5.3.1.1二元樹的先中後序遍歷
二元樹的遍歷
三種方法
先序遍歷
根,左右
中序遍歷
左,右,根
後序遍歷
左,右,根
遍歷演算法表達樹
先序遍歷得前綴表達式
中序遍歷得中綴表達式(沒有括號)
後序遍歷得後綴表達式
考點:求遍歷序列
分支結點逐層展開法
從你的全世界路過法
先序—第一次訪問時經過
中序—第二次訪問時路過
後序—第三次訪問時路過
5.3.1.2二元樹的層次遍歷
樹的層次遍歷思想
①初始化一個輔助隊列
②根節點入隊
③若隊列非空,則隊頭結點入隊,訪問該節點,並將其左右孩子插入隊列
④重複③直至隊列為空
5.3.1.3由遍歷序列構造二元樹
前序 中序遍歷序列
後序 中序遍歷序列
層序 中序遍歷序列
一定要有中序序列
5.3.2.1線索二元樹的概念
線索二元樹
作用:方便從一個指定結點出發,找到其前驅、後繼;方便遍歷
儲存結構
在普通二元樹結點的基礎上,增加兩個標誌位itag和rtag
itag==1時,表示ichild指向前驅;itag==0時,表示ichild指向左孩子
rtag==1時,表示rchild指向後繼;rtag==0時,表示ichild指向右孩子
三種線索二元樹
中序線索二元樹
以中序遍歷序列為依據進行“線索化”
先序線索二元樹
以先序遍歷序列為依據進行“線索化”
後序線索二元樹
以後序遍歷序列為依據進行“線索化”
幾個概念
線索
指向前驅/後繼的指標稱為線索
中序前驅/中序後繼;先序前驅/先序後繼;後續前驅/後續後繼
手刷畫出線索二元樹
①確定線索二元樹類型—中序、先序、or後序?
②依照對應遍歷規則,決定各結點的存取順序,並寫上編號
③將n 1個空鏈域連上前驅、後繼
5.3.2.2二元樹的線索化
中序線索化
得到中序線索二元樹
先序線索化
得到先序線索二元樹
後續線索化
得到後序線索二元樹
核心
中序/先序/後序遍歷演算法的改造,當存取一個結點時,連接該結點 與前驅結點的線索訊息
用一個指標pre記錄目前存取結點的前驅結點
易錯點
最後一個結點的rchild、rtag的處理
先序線索化中,注意處理轉圈問題,當itag==0時,才能對左子樹先序線索化
5.3.2.3在線索二元樹中找前驅後繼
若itag/rtag==0
自己可以推出來
5.4.1樹的儲存結構
樹、森林的儲存結構
雙親表示法
順序儲存結點數據,結點中保存父節點在數組中的下標
優點:找父節點方便;缺點;找孩子不方便
孩子表示法
順序儲存結點數據,結點中保存孩子鍊錶頭指標(順序 鍊式儲存)
優點:找孩子方便;缺點:找父節點不方便
孩子兄弟表示法
用二元鍊錶儲存結點—左孩子右兄弟
用於儲存森林時,將森林中每棵樹的根節點視為平級的兄弟關係
從儲存視角來看形態上和二元樹類似
5.4.2樹、森林與二元樹的轉換
key
本質:用孩子兄弟表示法儲存樹或森林,在形態上與二元樹類似
用孩子兄弟表示法儲存森林時,將森林每棵樹的根節點視為平級的兄弟關係
樹、森林轉二元樹
依「層序」依序處理每個結點
處理一個節點的方法是:如果目前處理的結點有孩子,就把所有孩子 結點“用右指針串成糖葫蘆”,並在二元樹中把第一個孩子掛在當前結點 的左指針下方
二元樹轉樹、森林
以「層序」恢復每個結點的孩子
如何恢復一個結點的孩子:在二元樹中,如果目前處理的結點有左孩子 ,就把左孩子和「一整串右指針糖葫蘆」拆下來,按順序掛在當前結點的下方
5.4.3樹和森林的遍歷
樹
先根遍歷
後根遍歷
森林
先序遍歷
中序遍歷
二元樹
先序遍歷
中序遍歷
第六章圖
6.1圖的基本概念
6.1.1圖的基本概念
定義:G=(V,E),頂點集V,邊集E
無向圖(無向邊/邊)、有向圖(有向邊/弧)
頂點的度、出度、入度(無向圖?有向圖?)
邊的權、帶權圖/網
點到點的關係
路徑、迴路、簡單路徑、簡單迴路
路徑長度
點到點的距離(最短路徑)
無向圖頂點的連通性、聯通圖
有向圖頂點的連通性、連通圖
圖的局部
子圖
連通分量—極大連通子圖
強連通分量—極大強連通子圖
連通無向圖的生成樹—包含全部頂點的極小連通子圖
非連通無向圖的生成森林—各連通分量的生成樹
幾種特殊形態的圖
完全圖
稠密圖、稀疏圖
樹、森林、有向樹
常見考點
對於n個頂點的無向圖G
所有頂點的度和=2|E|
若G是連通圖,則至少有n-1條邊(樹),若 |E|>n-1,則一定有迴路
若G是非連通圖,則最多可能有條邊
無向完全圖共有邊
對於n個頂點的有向圖G
所有頂點的度和=2|E|
若G是連通圖,則至少有n條邊(樹),形成迴路
所有頂點的出度之和=入度之和=|E|
有向完全圖共有邊
6.2圖的儲存及基本操作
鄰接矩陣
數組實現的順序存儲,空間複雜度高,不適合存儲稀疏圖
鄰接表
十字鍊錶
儲存有向圖
鄰接多重表
儲存無向圖
6.3圖的遍歷
6.3.1圖的廣度優先遍歷(BFS)
類似樹的層序遍歷(廣度優先遍歷)
演算法要點
需要一個輔助隊列
如何從一個結點找到與之鄰接的其他頂點
visited數組防止重複訪問
如何處理非連通圖
複雜度
空間複雜度:O(|V|)—輔助隊列
時間複雜度
訪問結點的時間➕訪問所有邊的時間
鄰接矩陣:O(|V|^2)
鄰接表:(|V| |E|)
廣度優先生成樹
由廣度優先遍歷決定的樹
鄰接表儲存的圖表示方式不唯一,遍歷序列,生成樹也不唯一
遍歷非聯通圖可廣度優先生成森林
圖的深度優先遍歷(DFS)
演算法要點
遞歸地深入探索未被訪問過的鄰接點(類似於樹的先根遍歷的實現)
如何從一個節點找到與之鄰接的其他頂點
visited數組防止重複訪問
如何處理非連通圖
複雜度分析
空間複雜度:O|V|—來自遞迴工作棧
時間複雜度
訪問結點的時間➕訪問所有邊的時間
鄰接矩陣:O(|V|^2)
鄰接表:O(|V| |E|)
深度優先生成樹
由深度優先遍歷決定的樹
鄰接表儲存的圖表示方式不唯一,深度優先遍歷序列,產生數也不唯一
深度優先遍歷非連通圖可得深度優先生成森林
圖的遍歷和圖的連通性
無向圖
DFS/BFS函數呼叫次數=連通分量數
有向圖
若從起始頂點到其他頂點都有路徑,只需呼叫一次DFS/BFS函數
對於強連通圖,從任一頂點出發都只需呼叫一次DFS/BFS函數
6.4圖的應用
6.4.1最小生成樹
Prim演算法(普里姆)
從某一個頂點開始建立生成樹; 每一次都將代價最小的新頂點納入生成樹 直到所有頂點都納入為止
Kruskal演算法(克魯斯卡爾)
每次選擇一條權值最小的邊,使這條邊的 兩頭連通(原本已經連通的就不選) 直到所有結點都連通
6.4.2最短路徑問題
單源最短路徑
BFS演算法(無權圖)
Dijkstra演算法(帶權圖,無權圖)
不適用於有負權值的帶權圖
各頂點間的最短路徑
Floyd演算法(附權圖、無權圖)
無法解決有「負權迴路」的圖,這種圖可能沒有最短路徑
子主題