计算机基础知识数据结构与算法,(计算机基础知识)[数据结构与算法] 图
第六章 圖
6.1 圖的定義和基本術語
圖: G=(V,E) Graph = (Vertex, Edge)
V: 頂點(數據元素)的有窮非空集合
E: 邊的有窮集合
完全圖: 任意兩個點都有一條邊相連
稀疏圖: 有很少邊或弧的圖(e < nlongn)
稠密圖: 有較多邊或弧的圖
網: 邊/弧帶權的圖
鄰接: 有邊/弧相連的兩個頂點之間的關系
存在(vi,vj).則稱這兩個點互為鄰接點
存在,則稱vi鄰接到vj,vj鄰接于vi
關聯(依附): 邊/弧與頂點之間的關系.
頂點的度: 與該頂點相關聯的邊的數目 記為TD(V)
在有向圖里面,頂點的度是入度和出度之和
入度記為 ID(V)
出度記為 OD(V)
提示: 有向樹就是僅一個頂點的入度為0,其余頂點的入度均為1的有向圖
路徑: 接續的邊構成的頂點序列
路徑長度: 路徑上面或弧的數目/權值之和
回路(環): 第一個頂點和最后一個頂點相同的路徑
簡單路徑: 除路徑起點和終點可以相同值外,其余頂點均不相同的路徑
簡單回路(簡單環): 除路徑起點和終點相同值外,其余頂點均不相同的路徑
例子:
連通圖(強連通圖)
權與網: 圖中邊或弧所具有的相關數稱為權.表明從一個頂點到另一個頂點的距離或耗費 帶權的圖稱為網
**子圖: **
連通分量
強連通分量
極小連通子圖: 該子圖是G的連通子圖,在該子圖中刪除任何一條邊,子圖不再連通
生成樹: 包含無向圖G所有頂點的極小連通子圖.
生成森林: 對非連通圖,由各個連通分量的生成樹的集合
例子
6.2 案例引入
六度空間理論
6.3 圖的類型定義
圖的抽象數據類型定義:
6.4 圖的存儲結構
老樣子,我們可以通過數組或者鏈表來表示圖
數組表示法(鄰接矩陣)
圖沒有順序存儲結構,但是我們可以通過二維數組來表示元素間的關系
無向圖鄰接矩陣表示法
特點:
無向圖的鄰接矩陣是對稱的(浪費空間了)
頂點i的度,就是第i行中1的個數
特別的,如果圖是完全圖,那么他的鄰接矩陣除了對角元素全是0,其余的都是1
有向圖鄰接矩陣表示法
特點
有向圖的鄰接矩陣可能是不對稱的
有向圖i頂點的度就是對應的第i行和第i列的1的個數的和
網的鄰接矩陣表示法
例子
鄰接矩陣的存儲表示
用兩個數組分別存儲頂點表和鄰接矩陣
#define MaxInt 32767 //表示極大值
#define MVNum 100 //最大頂點數
typedef char VerTexType; //設頂點的數據類型為字符型
typedef int ArcType; //假設邊的權值的類型為整型
typedef struct{
VerTexType vexs[MVNum];//頂點表
ArcType arcs[MVNum][MVNum]; //鄰接矩陣
int vexnum,arcnum; //圖的當前點數和邊數
}AMGraph; //adjacency Matrix Graph
這個是無向網的定義,那么我們定義其他的就更簡單了
算法思想
輸入總頂點數和總邊數
依次輸入點的信息存進頂點表中
初始化鄰接矩陣,使每個權值初始化為最大值
構造鄰接矩陣
算法6.1 采用鄰接矩陣表示法創建無向網
Status CreateUDN(AMGraph &G){
cin>>G.vexnum>>G.arcnum;
for(int i=0; i
cin>>G.vexs[i];
}
//初始化鄰接矩陣
for(int i =0; i
for(int j =0; j
G.arcs[i][j] = MaxInt;
}
}
//輸入參數(構造無向網)
for(k=0; k
cin>>v1>>v2>>W; //輸入一條邊所依附的頂點以及邊的權值
i = LocateVex(G,v1);
j = Locate(G,v2);//確定v1和v2在G中的位置
//賦值
G.arcs[i][j] =w;
G.arcs[j][i] = G.arcs[i][j];
}
return OK;
}
補充算法: 在圖中查找頂點
int LocateVex(AMGraph G, VertexType u){
//圖g中查找頂點u,存在就返回頂點表中的下標;否則返回-1
int i;
for(i =0; i
if(u == G.vex[i]) return i;
}
return -1;
}
鄰接矩陣表示法的優缺點
優點
直觀,簡單,好理解
方便檢查任意一對頂點之間是否存在邊
方便查找任一頂點的所有"鄰接點"(有邊直接相連的頂點)
方便計算任一頂點的度
缺點
邊的個數非常少的時候(稀疏圖),浪費空間(數組大小始終是n的平方)
不利于刪除和增加結點
浪費時間------統計稀疏圖中一共有多少條邊(不管怎樣都要執行n的平方)
鄰接表表示法(鏈式)
無向圖
頭結點
表結點
舉例
我們可以發現如下特點
鄰接表不唯一
若無向圖中有n個頂點,e條邊,則其鄰接表需n個頭結點和2e個表結點**,適合存儲稀疏圖**(時間復雜度就是O(n+e))
無向圖計算度非常方便,只需要計算這個頂點的表結點的個數就可以了
有向圖
因為找入度難,所以我們需要逆鄰接表
練習
圖的鄰接表存儲表示
頂點結構
typedef struct VNode{
verTexType data; //頂點的信息
ArcNode *firstarc; //指向第一條依附該頂點的邊的指針域
}VNode,AdjList[MVNum];
說明
弧的結點結構
#define MVNum 100 //最大頂點數
typedef struct ArcNode{
int adjvex; //該邊所指向的頂點的位置
struct ArcNode * nexttarc; //下一條邊的指針
OtherInfo info; //有關于這條邊的信息
}ArcNode;
圖的結構定義
typedef struct{
AdjList verices; //定義一個頂點表
int vexnum,arcnum; //記錄頂點和邊的個數
}ALGraph
采用鄰接表表示法創建無向網
算法思想
輸入總邊數和總頂點數
建立頂點表
依次輸入點的信息存入定點表
將指針域都置為NULL
創建鄰接表
依次輸入每條邊依附的兩個頂點
確定兩個頂點的序號i和j, 建立邊結點
將次邊結點分別插入到vi和vj對應的兩個邊鏈表的頭部(頭插法)
算法實現
Status CreateUDG(ALGraph &G){
cin>>G.vexnum>>G.arcnum;
//建立頂點表
for(int i=0 ;i
cin>>G.verices[i].data;
G.verices[i].firstarc ==NULL;
}
//初始化頂點表
for(int k = 0;k
cin>>v1>>v2;
i = LocateVex(G,v1);
j = Locate(G,v2);//確定v1和v2在G中的位置
//關鍵操作
p1 = new ArcNode;
p1 -> adjvex = j;
p1 ->nextarc = G.verticex[i].firstarc;
G.verticex[i].firstarc = p1;
p2 = new ArcNode;
p2 -> adjvex = i;
p2 ->nextarc = G.verticex[j].firstarc;
G.verticex[j].firstarc = p2;
}
}
鄰接表的優缺點以及和鄰接矩陣的關系
優點
方便找到任一頂點的所有"鄰接點"
節約稀疏圖的空間
對于無向圖,我們很方便就能找到頂點的度
缺點
對于有向圖,我們比較難找到頂點的入度,只能計算出度,所以我們需要逆鄰接表才行
不方便檢查任意一對頂點之間是否存在邊
兩者的聯系
鄰接表中的每個鏈表對應于鄰接矩陣中的一行,鏈表中結點的個數等于一行中非零元素的個數
區別:
對于任一確定的無向圖,鄰接矩陣是唯一的,但是鄰接表不唯一
鄰接矩陣的空間復雜度是O(n的平方),鄰接表的空間復雜度是(O(n+e))
用途: 鄰接矩陣用于稠密圖,而鄰接表用于稀疏圖
圖的鄰接表的改進
十字鏈表
firstin: 第一條入弧
firstout: 第一條出弧
tailvex: 弧尾的位置
headvex: 弧頭的位置
hlink: 弧頭相同的下一條弧
tlink:弧尾相同的下一條弧
鄰接多重表
6.5 圖的遍歷
遍歷定義: 從已給的連通圖中某一頂點出發,沿著一些邊訪問圖中所有的頂點,且使每個頂點僅被訪問依次,就叫做圖的遍歷,它就是圖的基本運算/
圖的特點
? 圖中可能存在回路, 且圖中的任一頂點都可能與其他頂點相相通, 在訪問完某個頂點之后可能會沿著某些邊又回到了曾經訪問過的頂點
解決方案
? 設置輔助數組visited[n],用來i標記被訪問過的頂點.
初始化狀態visited[i]為0
頂點i被訪問,改visited[i]為1,防止被多次訪問
6.5.1 深度優先搜索(Depth_First Search -----DFS)
鄰接矩陣表示的無向圖深度遍歷實現:
void DFS(AMGraph G,int v){
cout<
for(w =0; w< G.vexnum;w++){
if((G.arcs[v][w]!=0)&&(!visited[w])){
DFS(G,w);
}//w是v的鄰接點,如果w為訪問那么則遞歸調用DFS
}
}
DFS算法效率分析
如果用鄰接矩陣來表示圖,時間復雜度是O(n平方)
如果用鄰接表來表示圖,那么時間復雜度就是(O(n+e))
非連通圖的遍歷
多加一個步驟,遞歸調用完(棧空了)的時候,檢查visited是否還有沒有訪問的元素,如果有,那么就隨機從沒有訪問的頂點里面選一個繼續遍歷
6.5.2 廣度優先搜索(Breadth_First Search--------BFS)
算法實現(用隊列的思想,類似于二叉樹的層次遍歷)
void BFS(Grapg G, int v){
cout<
InitQueue(Q);
EnQueue(Q,v);
while(!QueueEmpty(Q)){
DeQueue(Q,u);
for(w = FirstAdjVex(G,u); w>=0; w = NextAdjVex(G,u,w))
if(!visited[w]){
cout<
visited[w] = true; EnQueue(Q,w);
}
}
}
時間復雜度只與存儲結構有關,而與搜索路徑無關.
6.6 圖的運用
概念回顧: 生成樹:“所有頂點均由邊連接再一起,但不存在回路的圖。
度優先搜索(Breadth_First Search--------BFS)
[外鏈圖片轉存中…(img-0SzD3K4C-1618713736320)]
算法實現(用隊列的思想,類似于二叉樹的層次遍歷)
void BFS(Grapg G, int v){
cout<
InitQueue(Q);
EnQueue(Q,v);
while(!QueueEmpty(Q)){
DeQueue(Q,u);
for(w = FirstAdjVex(G,u); w>=0; w = NextAdjVex(G,u,w))
if(!visited[w]){
cout<
visited[w] = true; EnQueue(Q,w);
}
}
}
時間復雜度只與存儲結構有關,而與搜索路徑無關.
總結
以上是生活随笔為你收集整理的计算机基础知识数据结构与算法,(计算机基础知识)[数据结构与算法] 图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 又有锦鲤中大奖!淘宝去彩票店进货了 快看
- 下一篇: html post举例,html pos