實驗目的:
1. 掌握圖的鄰接矩陣和鄰接表的存儲結構;
2. 驗證圖在不同存儲結構下遍歷操作的實現。
3. 掌握圖的實際應用
實驗內容:
采用鄰接矩陣/鄰接表建立圖(無向圖,有向圖,無向網絡,有向網絡);
采用深度優先/廣度優先搜索方式遍歷圖;
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <LIMITS.H>
using namespace std;
#define Status int
#define VRType int
#define InfoType char
#define VertexType char
#define ERROR 0
#define OK 1
#define TRUE 1
#define FALSE 0
#define INFINITY 0 //最大值
#define MAX_VERTEX_NUM 20 //最大頂點個數
bool visited[MAX_VERTEX_NUM];//訪問標志數組
typedef struct ArcCell//鄰接矩陣(元素)類型
{
VRType adj; //頂點關系(邊或弧),圖用1\0表示是否相鄰,網為權值
InfoType *info; //邊或弧的相關信息指針
} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct//圖的鄰接矩陣類型
{
VertexType vexs[MAX_VERTEX_NUM]; //頂點向量
AdjMatrix arcs; //鄰接矩陣
int vexnum,arcnum; //圖的頂點數和邊或弧數
} Mgraph;
void (*VisitFunc)(Mgraph G,int v);//函數變量
void Input(InfoType *info)//錄入弧
{
info=(char*)malloc(sizeof(char));
scanf("%c",&*info);
}
Status LocateVex(Mgraph &G,VertexType u)//若G中存在點u,則返回該點在圖中的位置
{
int Loc;
for(Loc=0; Loc<G.vexnum; Loc++)
{
if(G.vexs[Loc]==u)
{
return Loc;
}
}
return -1;
}
Status CreateDG(Mgraph &G)//采用鄰接矩陣表示法,構造有向圖G
{
int IncInfo,i,j,k;
char v1,v2;
printf("請輸入圖的頂點數(1~20):\n");
scanf("%d",&G.vexnum);
getchar();
printf("請輸入圖的弧數:\n");
scanf("%d",&G.arcnum);
getchar();
printf("各弧是否含有其他信息(1(有),0(沒有)):\n");
scanf("%d",&IncInfo);
getchar();
for(i=0; i<G.vexnum; i++)
{
printf("請輸入第%d個頂點:\n",i+1);
scanf("%c",&G.vexs[i]);
getchar();
}
for(i=0; i<G.vexnum; i++)
{
for(j=0; j<G.vexnum; j++)
{
G.arcs[i][j].adj=INFINITY;
G.arcs[i][j].info=NULL;
}
}
for(k=0; k<G.arcnum; k++)
{
printf("請輸入一條弧連接的頂點:\n");
printf("弧尾頂點:\n");//輸入一條弧依附的頂點
scanf("%c",&v1);
getchar();
printf("弧頭頂點:\n");
scanf("%c",&v2);
getchar();
i=LocateVex(G,v1);
j=LocateVex(G,v2);//確定v1和v2在G中的位置
G.arcs[i][j].adj=1;//v1和v2的連接關系
if(IncInfo)
{
Input(G.arcs[i][j].info);//若弧含有相關信息,則輸入
}
}
return OK;
}//CreateDG
Status CreateDN(Mgraph &G)//采用鄰接矩陣表示法,構造有向網G
{
int IncInfo,i,j,k,w;
char v1,v2;
printf("請輸入圖的頂點數(1~20):\n");
scanf("%d",&G.vexnum);
getchar();
printf("請輸入圖的弧數:\n");
scanf("%d",&G.arcnum);
getchar();
printf("各弧是否含有其他信息(1(有),0(沒有))\n");
scanf("%d",&IncInfo);
getchar();
for(i=0; i<G.vexnum; ++i) //構造頂點向量
{
printf("請輸入第%d個頂點:",i+1);
scanf("%c",&G.vexs[i]);
getchar();
}
for(i=0; i<G.vexnum; ++i) //初始化鄰接矩陣
{
for(j=0; j<G.vexnum; ++j)
{
G.arcs[i][j].adj=INFINITY;
G.arcs[i][j].info=NULL;
}
}
for(k=0; k<G.arcnum; ++k) //構造鄰接矩陣
{
printf("請輸入一條弧連接的頂點及權值\n");
printf("弧尾頂點:\n");//輸入一條弧連接的頂點及權值
scanf("%c",&v1);
getchar();
printf("弧頭頂點:\n");
scanf("%c",&v2);
getchar();
printf("權值:\n");
scanf("%d",&w);
getchar();
i=LocateVex(G,v1);
j=LocateVex(G,v2);//確定v1和v2在G中的位置
G.arcs[i][j].adj=w;//弧<v1,v2>的權值
if(IncInfo)
{
Input(G.arcs[i][j].info);//若弧含有相關信息,則輸入
}
}
return OK;
}//CreateDN
Status CreateUDG(Mgraph &G)//采用鄰接矩陣表示法,構造無向圖G
{
int IncInfo,i,j,k;
char v1,v2;
printf("請輸入圖的頂點數(1~20):\n");
scanf("%d",&G.vexnum);
getchar();
printf("請輸入圖的弧數:\n");
scanf("%d",&G.arcnum);
getchar();
printf("各弧是否含有其他信息(1(有),0(沒有))\n");
scanf("%d",&IncInfo);
getchar();
for(i=0; i<G.vexnum; ++i) //構造頂點向量
{
printf("請輸入第%d個頂點:",i+1);
scanf("%c",&G.vexs[i]);
getchar();
}
for(i=0; i<G.vexnum; ++i) //初始化鄰接矩陣
{
for(j=0; j<G.vexnum; ++j)
{
G.arcs[i][j].adj=INFINITY;
G.arcs[i][j].info=NULL;
}
}
for(k=0; k<G.arcnum; ++k) //構造鄰接矩陣
{
printf("請輸入一條弧連接的頂點\n");
printf("弧尾頂點:\n");//輸入一條弧依附的頂點
scanf("%c",&v1);
getchar();
printf("弧頭頂點:\n");
scanf("%c",&v2);
getchar();
i=LocateVex(G,v1);
j=LocateVex(G,v2);//確定v1和v2在G中的位置
G.arcs[i][j].adj=1;//v1和v2的連接關系
if(IncInfo)
{
Input(G.arcs[i][j].info);//若弧含有相關信息,則輸入
}
G.arcs[j][i]=G.arcs[i][j];//置<v1,v2>的對稱弧<v2,v1>
}
return OK;
}//CreateUDG
Status CreateUDN(Mgraph &G)//采用鄰接矩陣表示法,構造無向網G
{
int IncInfo,i,j,k,w;
char v1,v2;
printf("請輸入圖的頂點數(1~20):\n");
scanf("%d",&G.vexnum);
getchar();
printf("請輸入圖的弧數:\n");
scanf("%d",&G.arcnum);
getchar();
printf("各弧是否含有其他信息(1(有),0(沒有)):\n");
scanf("%d",&IncInfo);
getchar();
for(i=0; i<G.vexnum; ++i)
{
printf("請輸入第%d個頂點:",i+1);
scanf("%c",&G.vexs[i]);
getchar();
}//構造頂點向量
for(i=0; i<G.vexnum; ++i)
{
for(j=0; j<G.vexnum; ++j)
{
G.arcs[i][j].adj=INFINITY;
G.arcs[i][j].info=NULL;
}
}//初始化鄰接矩陣
for(k=0; k<G.arcnum; ++k) //構造鄰接矩陣
{
printf("請輸入一條弧連接的頂點及權值\n");
printf("弧尾頂點:\n");//輸入一條弧連接的頂點及權值
scanf("%c",&v1);
getchar();
printf("弧頭頂點:\n");
scanf("%c",&v2);
getchar();
printf("權值:\n");
scanf("%d",&w);
getchar();
i=LocateVex(G,v1);
j=LocateVex(G,v2);//確定v1和v2在G中的位置
G.arcs[i][j].adj=w;//弧<v1,v2>的權值
if(IncInfo)
{
Input(G.arcs[i][j].info);//若弧含有相關信息,則輸入
}
G.arcs[j][i]=G.arcs[i][j];//置<v1,v2>的對稱弧<v2,v1>
}
return OK;
}//CreateUDN
Status FirstAdjVex(Mgraph G,int v)//返回v的第一個鄰接頂點
{
int i;
if(v>=0&&v<G.vexnum)
{
for(i=0; i<G.vexnum; i++)
{
if(G.arcs[v][i].adj)
{
return i;
}
}
}
return -1;
}//FirstAdjVex
Status NextAdjVex(Mgraph G,int v,int w)//返回v的(相對於w的)下一個鄰接頂點
{
int i;
if(v>=0 && v<G.vexnum)
{
if(w>=0 && w<G.vexnum)
{
for(i=w+1; i<G.vexnum; i++)
{
if(G.arcs[v][i].adj)
{
return i;
}
}
}
}
return -1;
}//NextAdjVex
void Print_JZ(Mgraph G)//打印矩陣
{
int i,j;
for(i=0; i<G.vexnum; i++)
{
for(j=0; j<G.vexnum; j++)
{
printf("%d ",G.arcs[i][j].adj);
}
printf("\n");
}
}
void Print(Mgraph G,int v)
{
printf("%c",G.vexs[v]);
}
void DFS(Mgraph G,int v)
{
//從第v個頂點出發遞歸地深度優先遍歷圖G
int w;
visited[v]=TRUE;
VisitFunc(G,v);//訪問第v個頂點
for(w=FirstAdjVex(G,v); w>0; w=NextAdjVex(G,v,w))
{
if(!visited[w])
{
DFS(G,w);//對v的尚未訪問的鄰接頂點w遞歸調用DFS
}
}
}//DFS
void DFSTraverse(Mgraph G,void (*Print)(Mgraph G,int v))
{
//對圖G做深度優先遍歷
int v;
VisitFunc=Print;//使用全局變量VisitFunc,使DFS不必設函數指針參數
for(v=0; v<G.vexnum; ++v)
{
visited[v]=FALSE;//訪問標志數組初始化
}
for(v=0; v<G.vexnum; ++v)
{
if(!visited[v])
{
DFS(G,v);//對尚未訪問的頂點調用DFS
}
}
}//DFSTraverse
int main()
{
char Ch;
Mgraph G;
while(1)
{
system("cls");
printf("請選擇操作:\n");
printf("1.構造有向圖\n2.構造有向網\n3.構造無向圖\n4.構造無向網\n5.退出\n");
scanf("%c",&Ch);
getchar();
switch(Ch)
{
case '1':
CreateDG(G);//構造有向圖G
printf("有向圖G的鄰接矩陣為:\n");
Print_JZ(G);
printf("有向圖G的深度優先遍歷:\n");
DFSTraverse(G,Print);
getchar();
system("pause");
break;
case '2':
CreateDN(G);//構造有向網G
printf("有向網G的鄰接矩陣為:\n");
Print_JZ(G);
printf("有向網G的深度優先遍歷:\n");
DFSTraverse(G,Print);
getchar();
system("pause");
break;
case '3':
CreateUDG(G);//構造無向圖G
printf("無向圖G的鄰接矩陣為:\n");
Print_JZ(G);
printf("無向圖G的深度優先遍歷:\n");
DFSTraverse(G,Print);
getchar();
system("pause");
break;
case '4':
CreateUDN(G);//構造無向網G
printf("無向網G的鄰接矩陣為:\n");
Print_JZ(G);
printf("無向網G的深度優先遍歷:\n");
DFSTraverse(G,Print);
getchar();
system("pause");
break;
case '5':
exit(0);
break;
default:
printf("選擇錯誤!\n");
system("pause");
}
return 0;
}
}
運行效果如圖:
使用了鄰接矩陣和深度優先算法