圖的遍歷與輸出 (鄰接矩陣和鄰接表)
阿新 • • 發佈:2018-12-31
#include <iostream> #include <cstdio> #include "graph.h" using namespace std; int main() { freopen("data.in" , "r" , stdin); // cout << "\n ** 生成鄰接矩陣圖,並進行DFS遍歷輸出: "<< endl; // MGraph mg ; // createMGraph(mg); // DFSTraverse(mg) ; cout << "\n ** 生成鄰接表圖,並進行DFS遍歷輸出: "<< endl; ALGraph alg ; createAdjList(alg); DFSTraverse(alg) ; cout << "\n ** BFS遍歷輸出: "<< endl; BFSTraverse(alg); cout << "\n ** From NO.1 To No.4: " <<endl; if( !GetOnePath(alg, 1, 4)) cout << " NO Path " << endl; cout << endl; return 0 ; }
#ifndef GRAPH_H_INCLUDED #define GRAPH_H_INCLUDED #define N 20 typedef enum{UDG = 0,DG = 1} GraphKind ; // 圖型別:UDG無向圖,DG有向圖 typedef char T ; /***************************鄰接矩陣 ****************************/ typedef struct{ T vexs[N]; // 頂點向量 int arcs[N][N]; // 鄰接矩陣 int vexnum, arcnum; //頂點數,邊數 GraphKind kind ; // 圖型別 }MGraph ; /**********************鄰接表****************************/ /** 弧結點型別 */ typedef struct ArcNode { int adjvex; ArcNode *nextArc; }ArcNode ; /** 頭結點VNode,頭結點向量AdjList型別*/ typedef struct VNode { T data ; ArcNode * firstarc ; }AdjList[N] ; //VNode, /** 鄰接圖型別*/ typedef struct { AdjList vertices; //頭結點向量 int vexnum, arcnum; GraphKind kind; // UDG無向圖 ; DG有向圖 }ALGraph; /**************************基本操作 *******************************/ void createAdjList( ALGraph &g); void createMGraph( MGraph &g); void DFS( ALGraph g , int v ); void DFS( MGraph g , int v ); void DFSTraverse( MGraph g ); void DFSTraverse( ALGraph g ); bool GetOnePath( ALGraph g , int v ,int d ); /**輸出鄰接表圖中第v個頂點*/ inline void PrintNode(ALGraph g, int v); void BFSTraverse(ALGraph g); #endif // GRAPH_H_INCLUDED
/** createGraph.cpp 讀入資料,分別建立圖的兩種儲存"鄰接矩陣"和"鄰接表" 操作簡單但繁瑣,能用它們建立圖相應儲存結構,非重點 */ #include "iostream" #include "graph.h" using namespace std ; /* 建立圖的 鄰接表結構g */ void createAdjList( ALGraph &g) { int i ; cin >>(int&)g.kind; cin >> g.vexnum ; // 輸入頂點數 cin >> g.arcnum ; // 輸入弧數 /* 輸入結點資料,建立頭結點向量*/ for ( i = 1 ; i <= g.vexnum ; i++ ) { cin >> g.vertices[i].data ; g.vertices[i].firstarc = NULL ; } /*輸入弧(頭,尾),建立鄰接表*/ for ( i= 0 ; i < g.arcnum ; i++ ) { int head , tail ; cin >> head >> tail ; //生成邊結點 ArcNode * p = new ArcNode ; p->adjvex = tail ; //頭插 p->nextArc = g.vertices[head].firstarc ; g.vertices[head].firstarc = p ; if ( g.kind == UDG ) //無向圖,還需在尾結點的邊連結串列中插入結點 { ArcNode * p = new ArcNode ; p->adjvex = head ; p->nextArc = g.vertices[tail].firstarc ; g.vertices[tail].firstarc = p ; } } } /* 建立圖的 鄰接矩陣結構g */ void createMGraph( MGraph &g) { int i , j; cin >> (int&)g.kind; cin >> g.vexnum; // 輸入頂點數 cin >> g.arcnum; // 輸入弧數 /* 輸入結點資料,建立頂點向量*/ for ( i = 1 ; i <= g.vexnum ; i++ ) { cin >> g.vexs[i]; } /*輸入弧(頭,尾),建立鄰接表*/ for (i = 1 ; i <= g.vexnum ; i++) for (j = 1 ; j <= g.vexnum ; j++) g.arcs[i][j] = 0 ; for ( i= 1 ; i <= g.arcnum ; i++ ) { int head , tail ; cin >> head >> tail ; g.arcs[head][tail] = 1 ; if ( g.kind == UDG ) // 無向圖為對稱陣 { g.arcs[tail][head] = 1 ; } } }
/**
traverse.cpp
鄰接矩陣圖和鄰接表圖的 深度優先搜尋(遍歷)
鄰接表圖廣度優先搜尋(遍歷)
鄰接表圖的指定起點和終點的路徑搜尋
(有路則向前探索,無路則回溯.即為迷宮問題)*/
#include "iostream"
#include "graph.h"
#include <queue>
using namespace std ;
bool VISITED[N]; //訪問標誌向量
/**訪問標誌陣列全部初始化為“未訪問” */
inline void InitVisited( )
{
for(int i=0; i<N; i++)
VISITED[i] = false;
}
/**從某頂點出發,深度優先搜尋“鄰接矩陣”儲存的圖
*@g 鄰接矩陣
*@v 出發頂點編號 */
void DFS( MGraph g , int v )
{
VISITED[v] = true ;
cout << g.vexs[v] << " " ;
for ( int w = 1 ; w <= g.vexnum ; w++ )
{
if ( g.arcs[v][w] && !VISITED[w] )
DFS( g , w ) ;
}
}
/** 深度優先搜尋遍歷,"鄰接矩陣”圖
* @g 鄰接矩陣 */
void DFSTraverse( MGraph g )
{
int v ;
InitVisited();//標誌陣列初始化為false
for ( v = 1 ; v <= g.vexnum ; v++)
if ( !VISITED[v] ) DFS(g,v) ;
}
/************* 以下為鄰接表圖的操作**************
/**輸出鄰接表圖中第v個頂點*/
inline void PrintNode(ALGraph g, int v)
{
cout << g.vertices[v].data << " " ;
}
/**從某頂點出發,深度搜索”鄰接表“儲存的圖
* @g 鄰接表
* @v 出發頂點編號*/
void DFS( ALGraph g , int v )
{
ArcNode * p ;
VISITED[v] = true ;
PrintNode(g,v) ; //輸出第v個頂點
for ( p = g.vertices[v].firstarc ; p ; p = p->nextArc )
{
int w = p->adjvex ;
if ( !VISITED[w] )
DFS( g , w ) ;
}
}
/** 深度優先搜尋遍歷,"鄰接表”表示的圖
* @g 鄰接表*/
void DFSTraverse( ALGraph g )
{
int v ;
InitVisited();//標誌陣列初始化為false
for ( v = 1 ; v <= g.vexnum ; v++)
if ( !VISITED[v] )
DFS(g,v);
}
/**BFS 廣度優先遍歷圖 (需使用佇列,這裡使用STL的queue)
*@g 鄰接表圖
*/
void BFSTraverse(ALGraph g)
{
int v,w;
queue<int> q;
InitVisited();//標誌陣列初始化為false
for(v=1; v<=g.vexnum; v++)
{
if( !VISITED[v])
{
VISITED[v] = true;
PrintNode(g,v) ; //輸出第v個頂點
q.push(v);
while(q.size()!=0)
{
w = q.front();
q.pop();
for(ArcNode *p=g.vertices[w].firstarc; p; p=p->nextArc)
{
w = p->adjvex;
if(!VISITED[w])
{
VISITED[w] = true;
PrintNode(g,w) ; //輸出第w個頂點
q.push(w);
}
}//for
}//while
}
}
}
int PATH[100] ;// 儲存路徑
/** 基於DFS,輸出從v號到d號頂點的一條路徑 (即為迷宮問題)
* @g 鄰接表儲存的圖
* @v 起點編號
* @d 終點編號
* @len 從len開始儲存,即起點距當前頂點的距離
* @return 存在v到s路徑true,否則false */
bool GetOnePath( ALGraph g, int s, int d, int len )
{
ArcNode * p ;
//到達終點,則輸出路徑並返回
if ( d == s )
{
PATH[len] = s ;
for (int i = 1 ; i <= len ; i++)
PrintNode(g,PATH[i]) ;
return true;
}
//訪問(記入路徑)並標記
VISITED[s] = true ;
PATH[len] = s ;
for ( p = g.vertices[s].firstarc ; p ; p = p->nextArc )
{
// 從v的各個尚未訪問的鄰接點w出發 搜尋d
int nextNode = p->adjvex ;
if ( !VISITED[nextNode] )
if( GetOnePath(g, nextNode, d, len+1) )
return true ;
}
return false; //從起點s的各鄰接點出發(各方向)均無路可達,則無路
}
/** 尋路徑的包裝函式*/
bool GetOnePath( ALGraph g, int s, int d )
{
InitVisited();
return GetOnePath(g,s,d,1);
}
0 8 9
A B C D E F G H
1 2
1 3
2 4
2 5
3 6
3 7
4 8
5 8
6 7
1 4 4
A B C D
1 2
1 3
3 4
4 1