圖的存儲(chǔ)與遍歷

??圖的存儲(chǔ)與遍歷

一.實(shí)驗(yàn)?zāi)康?/b>

掌握?qǐng)D的存儲(chǔ)結(jié)構(gòu)以及圖的深度優(yōu)先搜索遍歷彤敛、最小生成樹(shù)算法掠抬。

二.實(shí)驗(yàn)要求與內(nèi)容

自構(gòu)造一無(wú)向圖,采用鄰接矩陣或者鄰接表存儲(chǔ)瓷耙,完成圖的深度優(yōu)先搜索遍歷以及廣度優(yōu)先搜索遍歷算法的實(shí)現(xiàn)朱躺。

算法參見(jiàn)課本P214-225

三.實(shí)驗(yàn)步驟

1.?dāng)?shù)據(jù)結(jié)構(gòu)

圖的儲(chǔ)存與遍歷的鄰接矩陣方式,在圖的深度優(yōu)先搜索中采用的是棧的方式進(jìn)行結(jié)點(diǎn)的儲(chǔ)存搁痛,在圖的廣度優(yōu)先搜索中用的是隊(duì)列方式進(jìn)行儲(chǔ)存长搀。隊(duì)列和棧用的都是stl中所定義好的,需要頭文件#include<queue>和#include<stack>

在最小生成樹(shù)中采用合并集的思想鸡典,定義一個(gè)結(jié)構(gòu)體來(lái)儲(chǔ)存邊的開(kāi)始點(diǎn)源请,結(jié)束點(diǎn),以及權(quán)值大小彻况。

2.算法設(shè)計(jì)

在深度優(yōu)先搜索中用棧的方式進(jìn)行儲(chǔ)存以訪問(wèn)過(guò)的結(jié)點(diǎn)谁尸,找到一個(gè)結(jié)點(diǎn)A后進(jìn)行訪問(wèn)標(biāo)記并壓入棧,訪問(wèn)與它相連的另一個(gè)結(jié)點(diǎn)B標(biāo)記并壓入棧纽甘,再訪問(wèn)結(jié)點(diǎn)B相連的任一結(jié)點(diǎn)標(biāo)記并壓入棧良蛮,重復(fù),悍赢,直至沒(méi)有結(jié)點(diǎn)N沒(méi)有可供訪問(wèn)的結(jié)點(diǎn)决瞳。則從棧中彈出頭結(jié)點(diǎn),尋找結(jié)點(diǎn)N-1的另外可供訪問(wèn)的結(jié)點(diǎn)左权,如果沒(méi)有則再?gòu)棾鲱^結(jié)點(diǎn)直至棧為空皮胡。

在廣度優(yōu)先搜索中用隊(duì)列的方式進(jìn)行儲(chǔ)存訪問(wèn)過(guò)的結(jié)點(diǎn),找到一個(gè)結(jié)點(diǎn)A后進(jìn)行訪問(wèn)標(biāo)記并進(jìn)入隊(duì)列赏迟,訪問(wèn)與它相連的所有結(jié)點(diǎn)標(biāo)記并進(jìn)入隊(duì)列屡贺,當(dāng)與它相連的所有結(jié)點(diǎn)都進(jìn)入隊(duì)列后頭結(jié)點(diǎn)出隊(duì),訪問(wèn)隊(duì)列頭結(jié)點(diǎn)的所有可供訪問(wèn)的結(jié)點(diǎn)并進(jìn)入隊(duì)列锌杀,甩栈,重復(fù),直至隊(duì)列為空

在這兩種訪問(wèn)方式中設(shè)置一個(gè)visited用來(lái)標(biāo)記該結(jié)點(diǎn)是否被訪問(wèn)過(guò)抛丽,如果未被訪問(wèn)過(guò)visited[i]=0否則visited[i]=1;

合并集求最小生成樹(shù)谤职,將每一個(gè)結(jié)點(diǎn)都看作成一棵樹(shù),將權(quán)值進(jìn)行排序亿鲜,求最小權(quán)值的start和end是否在一棵樹(shù)中允蜈,如果不在一棵樹(shù)中則將兩個(gè)結(jié)點(diǎn)并為一棵樹(shù),重復(fù)找最小權(quán)值和合并樹(shù)這兩個(gè)步驟直至所有結(jié)點(diǎn)都在一棵樹(shù)上為止蒿柳。

詳細(xì)過(guò)程解析看代碼注釋

3.程序

void DFS1(int v)//深度優(yōu)先搜索

{

? ? cout<<b[v]<<" ";//訪問(wèn)第v個(gè)結(jié)點(diǎn)

? ? visited[v]=1;//設(shè)置該結(jié)點(diǎn)已經(jīng)被訪問(wèn)過(guò)饶套;

? ? s.push(v);

? ? int count=1;

? ? while(!(s.empty()&& count==n))

? ? {

? ? ? ? if(s.empty() && count!=n)//需要判斷棧空但是結(jié)點(diǎn)并沒(méi)有遍歷完的情況

? ? ? ? {

? ? ? ? ? ? for(int i=1;i<=n;i++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? if(visited[i]==0)//如果該鄰接結(jié)點(diǎn)都還沒(méi)有被訪問(wèn)過(guò)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? cout<<b[i]<<" ";

? ? ? ? ? ? ? ? ? ? visited[i]=1;

? ? ? ? ? ? ? ? ? ? s.push(i);

? ? ? ? ? ? ? ? ? ? count++;

? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? int w=node1(s.top());//求該結(jié)點(diǎn)的鄰接結(jié)點(diǎn)

? ? ? ? while(w!=-1)//如果該結(jié)點(diǎn)存在鄰接結(jié)點(diǎn)

? ? ? ? {

? ? ? ? ? ? if(!visited[w])

? ? ? ? ? ? {

? ? ? ? ? ? ? ? cout<<b[w]<<" ";

? ? ? ? ? ? ? ? s.push(w);

? ? ? ? ? ? ? ? visited[w]=1;

? ? ? ? ? ? ? ? count++;

? ? ? ? ? ? }

? ? ? ? ? ? w=node1(w);

? ? ? ? }

? ? ? ? s.pop();

? ? }

}

void DFS(int v)//廣度優(yōu)先搜索

{

? ? cout<<b[v]<<" ";//訪問(wèn)第v個(gè)結(jié)點(diǎn)

? ? visited[v]=1;//設(shè)置該結(jié)點(diǎn)已經(jīng)被訪問(wèn)過(guò)垒探;

? ? q.push(v);

? ? int count=1;

? ? while(!(q.empty()&&count==n))

? ? {

? ? if(q.empty() && count!=n)//需要判斷隊(duì)列空但是結(jié)點(diǎn)并沒(méi)有遍歷完的情況

? ? {

? ? ? ? for(int i=1;i<=n;i++)

? ? ? ? {

? ? ? ? ? ? if(visited[i]==0)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? cout<<b[i]<<" ";

? ? ? ? ? ? ? ? visited[i]=1;

? ? ? ? ? ? ? ? q.push(i);

? ? ? ? ? ? ? ? count++;

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? int s=q.front();

? ? q.pop();

? ? int w=node1(s);//求該結(jié)點(diǎn)的鄰接結(jié)點(diǎn)

? ? while(w!=-1)//如果該結(jié)點(diǎn)存在鄰接結(jié)點(diǎn)

? ? {

? ? if(!visited[w])//如果該鄰接結(jié)點(diǎn)都還沒(méi)有被訪問(wèn)過(guò)

? ? {

? ? ? ? cout<<b[w]<<" ";

? ? ? ? q.push(w);

? ? ? ? visited[w]=1;

? ? ? ? count++;

? ? }

? ? ? ? w=node1(s);

? ? }

}

}

int find(int x)

{

? ? if(x!=pre[x])

? ? ? ? pre[x]=find(pre[x]);

? ? return pre[x];

}

void megre(int x,int y,int n)//查并集合并函數(shù)妓蛮,n 用來(lái)記錄最短路中應(yīng)該加入哪個(gè)點(diǎn)

{

? ? int fx=find(x);

? ? int fy=find(y);

? ? if(fx!=fy)

? ? {

? ? ? ? pre[fx]=fy;

? ? ? ? sum=edge[n].power+sum;

? ? }

}

4.程序調(diào)試

測(cè)試數(shù)據(jù)、程序運(yùn)行結(jié)果截圖


四.結(jié)果與體會(huì)

在使用棧和隊(duì)列的時(shí)候可以用stl中的棧的隊(duì)列圾叼,蛤克,無(wú)需自己定義函數(shù)捺癞,但需要加頭文件#include<queue>和#include<stack>

在求最小權(quán)值的時(shí)候可以用查并集的方法。

在廣度優(yōu)先搜索和深度優(yōu)先搜索的時(shí)候要特別考慮如果椆辜罚或者隊(duì)列為空時(shí)但是結(jié)點(diǎn)卻沒(méi)有遍歷完髓介。即輸入的圖并不是一棵樹(shù),可能是森林的情況下筋现。

五.源程序

另附

#include<iostream>

#include<queue>

#include<stack>

using namespace std;

#define M 100

int a[M][M];//鄰接矩陣

int b[M];//頂點(diǎn)數(shù)據(jù)

int visited[M];

queue<int> q;

stack<int>s;

int pre[M];

int sum=0;

struct node

{

? ? int start,end,power;

}edge[20];

int m,n;//無(wú)向圖的頂點(diǎn)數(shù)和邊數(shù)

int node1(int v)

{

? ? for(int i=1;i<=n;i++)

? ? {

? ? ? ? if(a[v][i]!=0 && visited[i]==0)

? ? ? ? ? ? return i;

? ? }

? ? return -1;//如果該結(jié)點(diǎn)的所有相連結(jié)點(diǎn)都被訪問(wèn)過(guò)

}

int cmp(node a,node b)//按權(quán)值排序

{

? ? return a.power<b.power;

}

int find(int x)

{

? ? if(x!=pre[x])

? ? ? ? pre[x]=find(pre[x]);

? ? return pre[x];

}

void megre(int x,int y,int n)//查并集合并函數(shù)唐础,n 用來(lái)記錄最短路中應(yīng)該加入哪個(gè)點(diǎn)

{

? ? int fx=find(x);

? ? int fy=find(y);

? ? if(fx!=fy)

? ? {

? ? ? ? pre[fx]=fy;

? ? ? ? sum=edge[n].power+sum;

? ? }

}

void DFS1(int v)//深度優(yōu)先搜索

{

? ? cout<<b[v]<<" ";//訪問(wèn)第v個(gè)結(jié)點(diǎn)

? ? visited[v]=1;//設(shè)置該結(jié)點(diǎn)已經(jīng)被訪問(wèn)過(guò);

? ? s.push(v);

? ? int count=1;

? ? while(!(s.empty()&& count==n))

? ? {

? ? ? ? if(s.empty() && count!=n)//需要判斷椃桑空但是結(jié)點(diǎn)并沒(méi)有遍歷完的情況

? ? ? ? {

? ? ? ? ? ? for(int i=1;i<=n;i++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? if(visited[i]==0)//如果該鄰接結(jié)點(diǎn)都還沒(méi)有被訪問(wèn)過(guò)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? cout<<b[i]<<" ";

? ? ? ? ? ? ? ? ? ? visited[i]=1;

? ? ? ? ? ? ? ? ? ? s.push(i);

? ? ? ? ? ? ? ? ? ? count++;

? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? int w=node1(s.top());//求該結(jié)點(diǎn)的鄰接結(jié)點(diǎn)

? ? ? ? while(w!=-1)//如果該結(jié)點(diǎn)存在鄰接結(jié)點(diǎn)

? ? ? ? {

? ? ? ? ? ? if(!visited[w])

? ? ? ? ? ? {

? ? ? ? ? ? ? ? cout<<b[w]<<" ";

? ? ? ? ? ? ? ? s.push(w);

? ? ? ? ? ? ? ? visited[w]=1;

? ? ? ? ? ? ? ? count++;

? ? ? ? ? ? }

? ? ? ? ? ? w=node1(w);

? ? ? ? }

? ? ? ? s.pop();

? ? }

}

void DFS(int v)//廣度優(yōu)先搜索

{

? ? cout<<b[v]<<" ";//訪問(wèn)第v個(gè)結(jié)點(diǎn)

? ? visited[v]=1;//設(shè)置該結(jié)點(diǎn)已經(jīng)被訪問(wèn)過(guò)一膨;

? ? q.push(v);

? ? int count=1;

? ? while(!(q.empty()&&count==n))

? ? {

? ? if(q.empty() && count!=n)//需要判斷隊(duì)列空但是結(jié)點(diǎn)并沒(méi)有遍歷完的情況

? ? {

? ? ? ? for(int i=1;i<=n;i++)

? ? ? ? {

? ? ? ? ? ? if(visited[i]==0)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? cout<<b[i]<<" ";

? ? ? ? ? ? ? ? visited[i]=1;

? ? ? ? ? ? ? ? q.push(i);

? ? ? ? ? ? ? ? count++;

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? int s=q.front();

? ? q.pop();

? ? int w=node1(s);//求該結(jié)點(diǎn)的鄰接結(jié)點(diǎn)

? ? while(w!=-1)//如果該結(jié)點(diǎn)存在鄰接結(jié)點(diǎn)

? ? {

? ? if(!visited[w])//如果該鄰接結(jié)點(diǎn)都還沒(méi)有被訪問(wèn)過(guò)

? ? {

? ? ? ? cout<<b[w]<<" ";

? ? ? ? q.push(w);

? ? ? ? visited[w]=1;

? ? ? ? count++;

? ? }

? ? ? ? w=node1(s);

? ? }

}

}

int main()

{

? ? //構(gòu)造無(wú)向圖,鄰接矩形

? ? cout<<"請(qǐng)輸入無(wú)向圖的頂點(diǎn)數(shù)和邊數(shù)";

? ? cin>>n>>m;

? ? for(int i=1;i<=n;i++)//初始化鄰接矩陣

? ? ? ? for(int j=1;j<=n;j++)

? ? ? ? ? ? a[i][j]=0;

? ? cout<<"請(qǐng)輸入頂點(diǎn)的順序";

? ? for(int i=1;i<=n;i++)

? ? {

? ? ? ? cin>>b[i];

? ? }

? ? cout<<"依次輸入每一條邊兩個(gè)頂點(diǎn)的序列號(hào)和權(quán)值"<<endl;

? ? for(int i=1;i<=m;i++)

? ? {

? ? ? ? int x,y,weight;

? ? ? ? scanf("%d %d %d",&x,&y,&weight);

? ? ? ? edge[i].start=x;

? ? ? ? edge[i].end=y;

? ? ? ? edge[i].power=weight;

? ? ? ? a[x][y]=weight;

? ? ? ? a[y][x]=weight;

? ? }

? ? //圖的廣度優(yōu)先搜索

?? cout<<"廣度優(yōu)先遍歷的結(jié)點(diǎn)順序?yàn)椋?<<endl;

? ? DFS(1);

? ? for(int i=1;i<=n;i++)

? ? ? ? visited[i]=0;

? ? //圖的深度優(yōu)先搜索

? ? cout<<endl;

? ? cout<<"深度優(yōu)先遍歷的結(jié)點(diǎn)順序?yàn)椋?<<endl;

? ? DFS1(1);

? ? cout<<endl;

? ? //求最小權(quán)值

? ? for(int i=1;i<=m;i++)

? ? ? ? pre[i]=i;

?? sort(edge+1,edge+m+1,cmp);

? ? for(int i=1;i<=m;i++)

? ? ? ? megre(edge[i].start,edge[i].end,i);

? ? cout<<"最小權(quán)值為:";

? ? cout<<sum<<endl;

?? return 0;

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末洒沦,一起剝皮案震驚了整個(gè)濱河市豹绪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌申眼,老刑警劉巖森篷,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異豺型,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)买乃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)姻氨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人剪验,你說(shuō)我怎么就攤上這事肴焊。” “怎么了功戚?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵娶眷,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我啸臀,道長(zhǎng)届宠,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任乘粒,我火速辦了婚禮豌注,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘灯萍。我一直安慰自己轧铁,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布旦棉。 她就那樣靜靜地躺著齿风,像睡著了一般药薯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上救斑,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天童本,我揣著相機(jī)與錄音,去河邊找鬼系谐。 笑死巾陕,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的纪他。 我是一名探鬼主播鄙煤,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼茶袒!你這毒婦竟也來(lái)了梯刚?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤薪寓,失蹤者是張志新(化名)和其女友劉穎亡资,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體向叉,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锥腻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了母谎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘦黑。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖奇唤,靈堂內(nèi)的尸體忽然破棺而出幸斥,到底是詐尸還是另有隱情,我是刑警寧澤咬扇,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布甲葬,位于F島的核電站,受9級(jí)特大地震影響懈贺,放射性物質(zhì)發(fā)生泄漏经窖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一梭灿、第九天 我趴在偏房一處隱蔽的房頂上張望钠至。 院中可真熱鬧,春花似錦胎源、人聲如沸棉钧。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)宪卿。三九已至的诵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間佑钾,已是汗流浹背西疤。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留休溶,地道東北人代赁。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像兽掰,于是被迫代替她去往敵國(guó)和親芭碍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 圖的定義與術(shù)語(yǔ) 1孽尽、圖按照有無(wú)方向分為無(wú)向圖和有向圖窖壕。無(wú)向圖由頂點(diǎn)和邊構(gòu)成,有向圖由頂點(diǎn)和弧構(gòu)成杉女≌胺恚弧有弧尾和弧頭之...
    unravelW閱讀 405評(píng)論 0 0
  • 1.把二元查找樹(shù)轉(zhuǎn)變成排序的雙向鏈表 題目: 輸入一棵二元查找樹(shù),將該二元查找樹(shù)轉(zhuǎn)換成一個(gè)排序的雙向鏈表熏挎。 要求不...
    曲終人散Li閱讀 3,314評(píng)論 0 19
  • -DFS(Depth First Search):深度優(yōu)先搜索 訪問(wèn)完一個(gè)頂點(diǎn)的所有鄰接點(diǎn)之后速勇,會(huì)按原路返回,對(duì)應(yīng)...
    Spicy_Crayfish閱讀 2,836評(píng)論 1 0
  • 1)這本書(shū)為什么值得看: Python語(yǔ)言描述坎拐,如果學(xué)的Python用這本書(shū)學(xué)數(shù)據(jù)結(jié)構(gòu)更合適 2016年出版快集,內(nèi)容...
    孫懷闊閱讀 12,466評(píng)論 0 15
  • 2018-7-21 姓名:張文清 公司:寧波大發(fā)化纖有限公司20天】 【知~學(xué)習(xí)】 《六項(xiàng)精進(jìn)》大綱背誦1遍,總(...
    z張文清閱讀 80評(píng)論 0 0