圖的儲存與遍歷(鏈式前向星中的DFS與BFS)
圖的儲存方式:
1.圖的陣列(鄰接矩陣)儲存表示,其中無向圖的儲存方式為對稱矩陣陣列,有向圖的儲存方式為非對稱矩陣陣列。求最短路徑時常常採用陣列儲存表示各點間的路徑。
2.邊集方法
邊的定義:stuct edge_set{
int u,v;
int weight;
}edge[N];
邊的結點:edge[i].u,edge[i].v
邊的權重:edge[i].weight
例如:
edge[0].u=1,edge[0].v=2,edge[0].weight=6edge[1].u=1,edge[0].v=3,edge[0].weight=3
edge[2].u=2,edge[0].v=4,edge[0].weight=9
edge[3].u=3,edge[0].v=4,edge[0].weight=5
3.圖的鄰接表儲存表示法
➢鄰接表是圖的一種鏈式儲存結構;
➢對圖中每個頂點建立一個單鏈表,第i個單鏈表中的結點表示依附於頂點vi的邊;由此通過遍歷每個頂點所對應的連結串列就可以遍歷所有的邊。
詳解以及陣列實現:https://www.cnblogs.com/ECJTUACM-873284962/p/6905416.html
但使用連結串列來實現鄰接表對於痛恨指標的的朋友來說,這簡直就是噩夢。於是便有了以結構體陣列形式來實現的方法,又稱
鏈式前向星。
4.鏈式前向星(鄰接表儲存的結構體陣列實現方法)
const int M=105; //結點數
const int oo=100000000;
struct node {
int to,next,weight;
} edge[M*100]; //M*100為邊數
int head[2*M]; //頭結點
構圖:
void add(int a, int b, int c) {
edge[tot].to=b; edge[tot].weight=c; edge[tot].next=head[a]; head[a]=tot++;
}
tot表示全域性變數,鄰接邊邊數;
head[a]儲存結點a的第一個邊的陣列edge下標,表示這條邊從a到edge[head[a]].to
edge[tot].next表示與這條邊相鄰的結點,初始化head[i]為-1,表示一開始沒有相鄰結點。
圖來源:https://www.cnblogs.com/LQ-double/p/5971323.html
如果要遍歷所有的點則for兩層迴圈就可以了。
—————————————————————————————我是分割線———————————————————————————————
圖的遍歷方式:
DFS(深度優先搜尋):從某個狀態開始,不斷遍歷可以到達的狀態直到狀態無法轉移,然後回退到前一步的狀態,然後繼續轉移到其他狀態,如此不斷重複,直到到達指定的狀態或求出解。
1.找到初始點V0,訪問此結點。
2.依次找到所有與V0鄰接的未被訪問的結點並進行深度優先搜尋遍歷圖。
3.直到所有與V0相通的點都被訪問。
圖解:
先看一幅有向圖
可以發現,其遍歷的順序為
0->3->1->2->4
其的概念就是一條路走到黑之後回頭到上一個路口換條路走
圖的表示方法包括鄰接表,鄰接矩陣等,鄰接矩陣表示的是用一個二維陣列表示圖的聯通,其中i行j列表示了i結點和j結點的聯通情況,如果其為1,說明是聯通的,如果其為0,反之;鄰接表表示的是一個一維陣列,但是陣列中每個列表包含著是連結串列;
看個圖加深理解:
其中a是有向圖/原圖,b是鄰接表表示圖,c是鄰接矩陣表示圖;
圖解來源:https://www.cnblogs.com/George1994/p/6399889.html
虛擬碼
遞迴實現
1. 訪問陣列初始化:visited[n] = 0
訪問頂點:visited[v] = 1
取v的第一個鄰接點w;
迴圈遞迴:
while(w存在)
if(w未被訪問過)
從頂點w出發遞迴執行;
w = v的下一個鄰接點;
非遞迴實現(使用棧的資料結構)
1. 棧初始化:visited[n] = 0
訪問頂點:visited[v] = 1
入棧
while(棧不為空)
x = 棧的頂元素,並且出棧;
if (存在並找到未被訪問的x的鄰接點w)
訪問w:visited[w] = 1
w進棧
實現程式碼(計算距離)
using namespace std;
struct node{
int to,nex,val;
}edge[200005];
int head[100005],cnt;//head[i]代表 以i結點開始的第一條邊的下標
void add(int u,int v,int w){
edge[cnt].to=v;
edge[cnt].val=w;
edge[cnt].nex=head[u];
head[u]=cnt;
cnt++;
}
void dfs(int t,int f,int w){
for(int i=head[t];~i;i=edge[i].nex){
int v=edge[i].to;
if(v==f)continue; //這裡的f代指父親結點,用來防止搜回去
dis[v]=w+edge[i].val;
dfs(v,t,w+edge[i].val);
}
}
int main(){
int n,m,i,j;
memset(head,-1,sizeof(head));
cin>>n>>m;
for(i=1;i<=m;i++){
int x,y,w;
cin>>x>>y;
w=1;
add(x,y,w);
add(y,x,w); //根據無向圖和有向圖兩種情況進行選擇性註釋此行
}
dfs(1,1,0);
return 0;
}
BFS(寬度優先搜尋):從某狀態開始訪問,不斷遍歷從該狀態訪問可以直接到達的狀態,然後從這些狀態出發,不斷訪問這些狀態可以直接到達的狀態,直到所有可以直接或間接到達的狀態都被訪問。(這種訪問方式需要藉助佇列實現)
先看一幅有向圖
可以發現,其遍歷的順序為
0->3->4->1->2
虛擬碼
非遞迴實現
1. 初始化佇列:visited[n] = 0
2. 訪問頂點:visited[v] = 1
3. 頂點v加入佇列
4. 迴圈:
while(佇列是否為空)
v = 佇列頭元素
w = v的第一個鄰接點
while(w存在)
if(如果w未訪問)
visited[w] = 1;
頂點w加入佇列
w = 頂點v的下一個鄰接點
上面的尋找下一個鄰接點,是尋找之前結點的下一個鄰接點,而不是當前的,否則就變成DFS了;
實現程式碼:
struct node{
int to,nex,val;
}edge[200005];
int head[100005],cnt;//head[i]代表以i結點開始的第一條邊的下標
void add(int u,int v,int w)
{
edge[cnt].to=v;
edge[cnt].val=w;
edge[cnt].nex=head[u];
head[u]=cnt;
cnt++;
}
int vis[100005];
queue<int>tp;
int main(){
int n,m,i,j;
memset(head,-1,sizeof(head));
cin>>n>>m;
for(i=1;i<=m;i++)
{
int x,y,w;
cin>>x>>y;
w=1;
add(x,y,w);
// add(y,x,w); //根據無向圖和有向圖兩種情況進行選擇性註釋此行
}
vis[1]=1;
tp.push(1);
while(!tp.empty()){
int f=tp.front();
tp.pop();
for(i=head[f];~i;i=edge[i].nex)
{
int v=edge[i].to;
if(vis[v]) continue;
vis[v]=vis[f]+1;
tp.push(v);
}
}
return 0;
}
鏈式前向星的優點在於可以通過該表示式:for(int i=head[u];~i;i=edge[i].next),很好的對各個點所連有的點進行遍歷。通常在題目中只需執行起始頂點的相應bfs/dfs函式,即可完成對整個圖的遍歷。
相關推薦
圖的儲存與遍歷(鏈式前向星中的DFS與BFS)
圖的儲存方式:1.圖的陣列(鄰接矩陣)儲存表示,其中無向圖的儲存方式為對稱矩陣陣列,有向圖的儲存方式為非對稱矩陣陣列。求最短路徑時常常採用陣列儲存表示各點間的路徑。2.邊集方法 邊的定義: stuct edge_set{
鄰接表存圖(鏈式前向星或vector)
#include<bits/stdc++.h> #define maxn 100005 using namespace std; // 鏈式前向星 常數優秀,使用結構體可獲得更優秀的常數 int info[maxn],to[maxn<<1],Prev[maxn&
洛谷P3371單源最短路徑Dijkstra版(鏈式前向星處理)
jks 沒有 style bool while add 是什麽 最短 短路徑 首先講解一下鏈式前向星是什麽。簡單的來說就是用一個數組(用結構體來表示多個量)來存一張圖,每一條邊的出結點的編號都指向這條邊同一出結點的另一個編號(怎麽這麽的繞) 如下面的程序就是存鏈式前向星。(
圖的儲存-鏈式前向星(池子法)(可用於樹形dp建樹)
歡迎點選檢視 不過您仍可閱讀本文在網易部落格的副本: ====================================================== “鏈式前向星”是我創造的(至少Baidu上沒有搜到)名詞,或許這種資料結構有其他更加正規易懂的名字,但我還是沒有搜到。(有一個資
三種存圖方式(鄰接矩陣,鄰接表,鏈式前向星)
#include<cstdio> #include<vector> #include<cstring> #include<algorithm> #include <iostream> using namespace std; const i
樹、簡單圖的儲存方法——鄰接矩陣 鄰接表 和 鏈式前向星 學習筆記
ps:樹是一種特殊的圖,樹有自己特殊的儲存方式,圖的儲存方式都能應用於樹。 對於圖、樹來講,一般給出一個n表是有n個節點(標號1~n)m個二元組(a,b)表示ab之間有一條邊。這樣就能確定一個圖。 對於樹來講沒有環,所以m=n-1 part one、鄰接矩陣 鄰接矩陣
前向星+鏈式前向星 ——圖的儲存
轉載連結 一、前向星 1、 我們首先來看一下什麼是前向星. 前向星是一種特殊的 邊集 陣列 ,我們把邊集陣列中的每一條邊按照起點從小到大排序, 如果起點相同就按照終點從小到大排序, 並記錄下以某個點為起點的所有邊在陣列中的起始位置和儲存長度,那麼前向星就構
UESTC30-最短路-Floyd最短路、spfa+鏈式前向星建圖
ring 輸入 sam -m 努力 成都 edge 輸出 工作 最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校賽裏,所有進入決
算法筆記--圖的存儲之鏈式前向星
算法筆記 div soft 鏈式前向星 target href 圖的存儲 blank 所有 鏈式前向星 這個博客寫的不錯:http://www.cnblogs.com/Tovi/p/6194786.html 模板: ①add_edge void add_e
最短路 spfa 算法 && 鏈式前向星存圖
.com mem ont .aspx 百度 dfs edit 時間復雜度 tails 推薦博客 https://i.cnblogs.com/EditPosts.aspx?opt=1 http://blog.csdn.net/mcdonnell_douglas/
POJ 3159 Candies(差分約束+spfa+鏈式前向星)
void tdi div con pre ace != view ash 題目鏈接:http://poj.org/problem?id=3159 題目大意:給n個人派糖果,給出m組數據,每組數據包含A,B,C三個數,意思是A的糖果數比B少的個數不多於C,即B的糖果數 -
鏈式前向星(轉)
img detail pre nlog 避免 target 我們 ext edge 轉自大佬博客https://blog.csdn.net/ACdreamers/article/details/16902023 我們首先來看一下什麽是前向星. 前向星是一種特殊的邊
存圖-深度理解鏈式前向星
前向星 在接觸鏈式前向星之前,先了解一下什麼是前向星。 前向星就是一種邊集陣列。我們先把每條邊的起點按照從小到大的順序排序如果起點一樣,那麼就按照終點從小到達來排 序。並記錄下以某個點為起點的所有邊在陣列中的起始位置和邊的數量,那麼前向星就構造好了。 head[i]表示以i為起點
Python實現二叉樹的建立以及遍歷(遞迴前序、中序、後序遍歷,隊棧前序、中序、後序、層次遍歷)
class Node: def __init__(self,data): self.data=data self.lchild=None self.rchild=None class Tree: def __init__(se
鏈式前向星(系列)
看名字很難,實際上賊簡單... 本蒟蒻瑟瑟發抖,請大佬們不要噴... 寫的有點長,如果覺得讀不下去... 肯定讀的下去,我寫得多通俗易懂啊! 不要管右面的表格...看左面的圖...好,讓我們開始: PS:n代表點的個數,m代表邊的個數 Part 1:鄰接矩陣 先列出來矩陣,然
P1462 通往奧格瑞瑪的道路(SPFA+鏈式前向星+二分)
題目背景 在艾澤拉斯大陸上有一位名叫歪嘴哦的神奇術士,他是部落的中堅力量 有一天他醒來後發現自己居然到了聯盟的主城暴風城 在被眾多聯盟的士兵攻擊後,他決定逃回自己的家鄉奧格瑞瑪 題目描述 在艾澤拉斯,有n個城市。編號為1,2,3,...,n。 城市之間有m條雙向的公路,連線著
存圖方法之鏈式前向星+BFS例項精講
存圖方法有很多,最暴力的方法就是開一個二維陣列 int maze[1000][1000]; //最多能大概5000 5000 int a, b, c; // 一條從a到b的權值為c的邊 while( cin >> a >> b >>
BFS與反向BFS,鏈式前向星與反向建邊
題目描述 在有向圖G 中,每條邊的長度均為1 ,現給定起點和終點,請你在圖中找一條從起點到終點的路徑,該路徑滿足以下條件: 1 .路徑上的所有點的出邊所指向的點都直接或間接與終點連通。 2 .在滿足條件1 的情況下使路徑最短。 注意:圖G 中可能存在重邊和自環,題目保證終點沒有出邊。 請你輸出符合條件的路徑
POJ 2387 經典解法,優先佇列的dijkstra+鏈式前向星儲存
這是很經典的解法,採用鏈式前向星的方式儲存邊,最短路Dijkstra+優先佇列。時間複雜度減少很多 Til the Cows Come Home Time Limit: 1000MSMemory Limit: 65536KTotal Submissions:
鏈式前向星
前向星 span 鏈式前向星 pan ont 學會 family style mil 鏈式前向星 鏈式前向星 鏈式前向星 重要的事情說三遍 明天不學會鏈式前向星我絕食三天鏈式前向星