【c/c++ 演算法/資料結構】 鄰接矩陣表示圖,深度,廣度優先遍曆 演算法設計+代碼+圖片__JAVA

來源:互聯網
上載者:User

http://wenku.baidu.com/link?url=fCPps803r8as33U38hMJ8ZtekPooj76vScbCtvS_PMO7FNdgmXhAeQlbeJT_jzQUMGFk4AWuGrUUfsumJPJPuycU-oikupB4gaCoWlVCynO

 

 

*問題描述:

建立圖的儲存結構(圖的類型可以是有向圖、無向圖、有向網、無向網,學生可以任選兩種類型),能夠輸入圖的頂點和邊的資訊,並儲存到相應儲存結構中,而後輸出圖的鄰接矩陣。

 

1、鄰接矩陣標記法:

  設G=(V,E)是一個圖,其中V={V1,V2,V3…,Vn}。G的鄰接矩陣是一個他有下述性質的n階方陣:

       1,若(Vi,Vj)∈E 或<Vi,Vj>∈E;

   A[i,j]={

0,反之

圖5-2中有向圖G1和無向圖G2的鄰接矩陣分別為 M1和 M2:

M1=┌ 0 1 0 1 ┐

│ 1 0 1 0 │

│ 1 0 0 1 │

└ 0 0 0 0 ┘          

M2=┌ 0 1 1 1 ┐

│ 1 0 1 0 │

│ 1 1 0 1 │

└ 1 0 1 0 ┘

  注意無向圖的鄰接是一個對稱矩陣,例如 M2。

  用鄰接矩陣標記法來表示一個具有n個頂點的圖時,除了用鄰接矩陣中的n*n個元素儲存頂點間相鄰關係外,往往還需要另設一個向量儲存n個頂點的資訊。因此其類型定義如下:

 VertexType vertex[MAX_VERTEX_NUM]; // 頂點向量

  AdjMatrix arcs; // 鄰接矩陣

int vexnum, arcnum; // 圖的當前頂點數和弧(邊)數

  GraphKind kind; // 圖的種類標誌  

若圖中每個頂點只含一個編號i(1≤i≤vnum),則只需一個二維數組表示圖的鄰接矩陣。此時儲存結構可簡單說明如下:

 type adjmatrix=array[1..vnum,1..vnum]of adj;

  利用鄰接矩陣很容易判定任意兩個頂點之間是否有邊(或弧)相聯,並容易求得各個頂點的度。

  對於無向圖,頂點Vi的度是鄰接矩陣中第i行元素之和,即

        n        n

    D(Vi)=∑A[i,j]  (或∑A[i,j])

        j=1         i=1

  對於有向圖,頂點Vi的出度OD(Vi)為鄰接矩陣第i行元素之和,頂點Vi的入度ID(Vi)為第i列元素之和。即

        n         n

    OD(Vi)=∑A[i,j], OD(Vi)=∑A[j,i])

        j=1         j=1    

  用鄰接矩陣也可以表示帶權圖,只要令

         Wij, 若<Vi,Vj>或(Vi,Vj)

    A[i,j]={

         ∞ , 否則。

  其中Wij為<Vi,Vj>或(Vi,Vj)上的權值。相應地,網的鄰接矩陣表示的類型定義應作如下的修改:    adj:weightype ; {weightype為權類型}

  圖5-6列出一個網和它的鄰接矩陣。

┌∞31∞∞┐

│∞∞51∞│

│∞∞∞∞∞│

│∞∞6∞∞│

└∞322∞┘

(a)網             (b)鄰接矩陣

圖5-6 網及其鄰接矩陣

  對無向圖或無向網路,由於其鄰接矩陣是對稱的,故可採用壓縮存貯的方法,僅存貯下三角或上三角中的元素(但不含對角線上的元素)即可。顯然,鄰接矩陣標記法的空間複雜度O( )。

無向網鄰接矩陣的建立方法是:首先將矩陣A的每個元素都初始化成∞。然後,讀入邊及權值(i,j,wij),將A的相應元素置成Wij。

 

2、圖的遍曆:

*深度優先搜尋

深度優先搜尋遍曆類似於樹的先根遍曆,是樹的先根遍曆的推廣。假設初始狀態是圖中所有的頂點未曾被訪問,則深度優先遍曆可從圖的某個頂點V出發,訪問此頂點,然後依次從V的未被訪問的鄰接點出發深度優先遍曆圖,直至圖中所有和V有路徑相通的頂點都被訪問到;若此時圖中尚有頂點未被訪問,則另選圖中的一個未被訪問的頂點,重複上述過程,直至圖中所有頂點都被訪問到為止。

以圖7.13(a)中無向圖G4為例,深度優先遍曆圖的過程如圖7.13(b)所示。假設從頂點V1出發進行搜尋,在訪問了頂點V1後,選擇鄰接點V2。因為V2未曾訪問,則從V2出發進行搜尋。依次類推,接著從V4,V8,V5出發進行搜尋。在訪問了V5之後,由於V5的鄰接點已都被訪問,則搜尋回到V8。由於同樣的理由,搜尋繼續回到V4,V2直至V1,此時由於V1的另一個鄰接點為被訪問,則搜尋又從V1到V3,再繼續進行下去。由此得到頂點的訪問序列為:

V1V2    V4V8V5V3V6V7

顯然,這是一個遞迴的過程。為了在遍曆過程中便於區別頂點是否已被訪問,需附設訪問標誌數組visted[0...n-1],其初值為0,一但某個頂點被訪問,則其相應的分量置為1。

*廣度優先搜尋

    假設從圖中某頂點v出發,在訪問了v之後一次訪問v的各個未曾訪問的擴大鄰接點,然後分別從這些鄰接點出發依次訪問他們的鄰接點,並使“先被訪問的鄰接點”先於“後被訪問的鄰接點”被訪問,直至圖中所有已被訪問的頂點的鄰接點都被訪問到。若圖中尚有頂點未被訪問,則另選圖中一個未曾被訪問的頂點作起始點,重複上述過程,直到圖中的頂點都被訪問為止。換句話說,廣度優先遍曆圖的過程就是以v為起始點,有遠至近,依次訪問和v有路徑相通且路徑長度為1、2……的頂點。例如,對圖G4進行廣度優先搜尋遍曆的過程如圖7.13(3)所示,首先訪問v1和v1的鄰接點v2和v3,然後依次訪問v2的鄰接點v4和v5及v3的鄰接點v6和v7,最後訪問v4的鄰接點v8。由於這些頂點的鄰接點均已被訪問,並且圖中所有頂點都被訪問,由此完成了圖的遍曆。得到的頂點訪問序列為

V1V2   V3     V4     V5V6     V7    V8

和深度優先搜尋類似,在遍曆的過程中也需要一個訪問標誌數組。並且,為了順次訪問路徑長度為2、3、…的頂點,需附設隊列以儲存已被訪問的路徑長度為1、2…的頂點。

2、圖的輸出

圖的鄰接矩陣是一個二維數組,運用for語句的嵌套依次輸出。

 

 

 

 

 

 

 

開始

 

開始

 

                                         

輸入vexnum,arcnum

IncInfo

 

i=i+1

選擇圖的類型

 

 

 

構造圖

 

 

 

 

 

輸入頂點

i<vexnum

 

 

 

                 Y

深度遍曆

 

 

 

 

廣度遍曆

 

 

j=j+1

       N

i<vexnum

 

 

 

初始化鄰

接矩陣

 

 

 

 

結束

                Y

j<vexnum

 

      N                    Y

i=i+1

                      N                 主程式流程圖

k<arcnum

 

 

 

k=k+1

 

 

輸入弧的資訊

設定鄰接矩陣

 

 

               Y

       N

結束

 

 

圖的構造流程圖

 

 

 

1、無向圖鄰接矩陣的建立演算法如下:

procedure build-graph;    {建立無向圖的鄰接矩陣}

begin

for i:=1 to n do read(G.vertex[i]);  {讀入n個頂點的資訊}

for i:=1 to n do

for j:=1 to e do

G.arcs[i][j]=0;

{將鄰接矩陣的每個元素初始化成0 }

for k:=1 to e do {e為邊的數目}

[ read(i,j,w)  {讀入邊<i,j>和權}G.arcs[i][j]:=w]

G.arcs[i][j]=G.arcs[i][i]{置對稱弧}

end;

該演算法的執行時間是O(n+n2+e),其中消耗在鄰接矩陣初始化操作上的時間是O(n2),而e<n2,所以上述演算法的時間複雜度是O(n2)。

2、無向網鄰接矩陣的建立演算法如下:

procedure build-graph;    {建立無向網的鄰接矩陣}

begin

for i:=1 to n do read(G.vertex[i]);  {讀入n個頂點的資訊}

for i:=1 to n do

for j:=1 to e do

G.arcs[i][j]=maxint;

{將鄰接矩陣的每個元素初始化成maxint,電腦內∞用最大事數maxint表示}

for k:=1 to e do {e為邊的數目}

[ read(i,j,w)  {讀入邊<i,j>和權}G.arcs[i][j]:=w;G.arcs[i][j]:=w]end;

該演算法的執行時間是O(n+n2+e),其中消耗在鄰接矩陣初始化操作上的時間是O(n2),而e<n2,所以上述演算法的時間複雜度是O(n2)。

3、圖的深度優先遍曆演算法分析

begin

for i:=1 to n do(visited[i]){初始化標誌數組}

while (i<n)

{for:i=1 to n do{按要求訪問鄰接點}}

end

當用二維數組表示鄰接矩陣作圖的儲存結構時,尋找每個頂點的鄰接點所需時間為O(n2),其中n為圖中頂點數。

4、圖的廣度優先遍曆演算法分析

begin

for i:=1 to n do(visited[i]){初始化標誌數組}

while (i<n)

{for:i=1 to n do{if…..if…..}}

end

 

二維數組表示鄰接矩陣作圖的儲存結構,其中n為圖中頂點數,尋找每個頂點的鄰接點所需時間為O(n2)。

 

/* Graph.h */

#include<stdio.h>

#include<malloc.h>

#include<conio.h>

#include<stdlib.h>

#include<string.h>

 

#define ERROR 0

#define OK 1

#define MAX_VERTEX_NUM 20 //定義最大值

#define INFINITY 32768 //定義極大值

#define MAX_INFO 20

 

typedefint VrType; //定義新的類型

typedefint InfoType;

typedefchar VertexType;

 

typedefenum

{DG,DN,UDG,UDN}GraphKind;//有向圖,有向網,無向圖,無向網

typedefstruct ArcCell 

{//鄰接矩陣標記法的各個資料結構

  VrType adj; // 頂點關聯類型。對無權圖,用或表示相鄰否;對帶權圖,則為權實值型別。

  InfoType *info; // 該弧相關資訊的指標

} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedefstruct

{

  VertexType vertex[MAX_VERTEX_NUM]; // 頂點向量

  AdjMatrix arcs; // 鄰接矩陣

int vexnum, arcnum; // 圖的當前頂點數和弧(邊)數

  GraphKind kind; // 圖的種類標誌

} MGraph;

typedefstruct

{//設定棧

int elem1[MAX_VERTEX_NUM];

int top;

}SeqStack;

 

int LocateVertex(MGraph G,VertexType v);

void CreateUDG(MGraph &G);

void CreateUDN(MGraph &G);   

void DepthFirstSearch1(MGraph G);

void BreadthFirstSearch1(MGraph G);

int CreateGraph(MGraph &G);

void Display(MGraph G);

 

 

 

/*  Graph.cpp   */

#include"Graph.h"

int LocateVertex(MGraph G,VertexType v)

{//用於返回輸弧端點所表示的數值

int j=0,k;

for(k=0;k<G.vexnum;++k)

if(G.vertex[k]==v)

{j=k;break;}

return(j);

}

 

void CreateUDG(MGraph &G)

{ // 採用數組(鄰接矩陣)標記法,構造無向圖

int i,j,k,IncInfo;

//i,j,k為計數器,IncInfo為標誌符

char ch; //用於吃掉多餘的字元

  VertexType v1,v2; //用於放置輸入的弧的兩個頂點

  printf("請輸入無向圖G的頂點數,邊數,弧是否含相關資訊(是:,否:): \n");

  scanf("%d,%d,%d",&G.vexnum,&G.arcnum,&IncInfo);

  ch=getchar(); //用於吃掉斷行符號

  printf("請輸入%d個頂點的值(1個字元,空格隔開):\n",G.vexnum);

for(i=0;i<G.vexnum;++i) // 構造頂點向量

     {

        scanf("%c",&G.vertex[i]);ch=getchar();

      }

  printf("請輸入%d條邊的頂點頂點(以空格作為間隔): \n",G.arcnum);

for(i=0;i<G.vexnum;++i) // 初始化鄰接矩陣

for(j=0;j<G.vexnum;++j)

     {

           G.arcs[i][j].adj=0;

           G.arcs[i][j].info=NULL; // {adj,info}

         }

for(k=0;k<G.arcnum;++k)

  {

        scanf("%c %c",&v1,&v2);

         ch=getchar();// ch吃掉斷行符號符

         i=LocateVertex(G,v1);  j=LocateVertex(G,v2);

if(IncInfo)scanf("%d",&G.arcs[i][j].info);

         G.arcs[i][j].adj=G.arcs[j][i].adj=1; // 置<v1,v2>的對稱弧<v2,v1>

      }

}//CreateUDG

 

void CreateUDN(MGraph &G)

{ // 採用數組(鄰接矩陣)標記法,構造無向網

int i,j,k,w,IncInfo;

//i,j,k為計數器,w用於放置權值,IncInfo為標誌符

char ch; //用於吃掉多餘的字元

  VertexType v1,v2;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.