实验四 图的应用
一、 实验题目:
图的应用——深度优先和广度优先搜索遍历
二、 实验内容:
很多涉及图上操作的算法都是以图的遍历操作为基础的。试编写程序,实现图的深度优先和广度优先搜索遍历操作。
要求:分别以邻接矩阵和邻接表作为存储结构,以用户指定的顶点为起始点,实现无向连通图的深度优先及广度优先搜索遍历,并输出遍历的结点序列。
提示:首先,根据用户输入的顶点总数和边数,构造无向图,然后以用户输入的顶点为起始点,进行深度优先、广度优先搜索遍历,并输出遍历的结果。
三、 实验要求:
1. 使用C语言完成算法设计和程序设计并上机调试通过。
2. 撰写实验报告,提供实验结果和数据。
3. 写出算法设计小结和心得。
四、 程序源代码:
#include<stdio.h>
#include<stdlib.h>
#define maxsize 20
#define TRUE 1
#define FALSE 0
int n,e;
char MG[20];
//广度的结构体定义
typedef struct {
char vexs[maxsize];
int arcs[maxsize][maxsize];
}MGraph;
typedef struct {
char data[maxsize];
int front,rear;
}LinkQueue;
typedef struct ArcNode{
int adjvex;
struct ArcNode *nextarc;
}ArcNode;
typedef struct{
char data;
ArcNode *firstarc;
}VNode;
VNode g[maxsize];
MGraph G;
LinkQueue Q;
int Locate(char v)
{
int i;
for(i=1;i<n;i++)
if(MG[i]==v) return i;
}
bool QueueEmpty(LinkQueue &Q) {
if(Q.front==Q.rear) return true;
else
return false;
}
int EnQueue(LinkQueue &Q,int k){
if(Q.front==(Q.rear+1)%maxsize){
printf("队列已满!\n");
return FALSE;
}
else{
Q.rear=(Q.rear+1)%maxsize;
Q.data[Q.rear]=k;
}
}
int DeQueue(LinkQueue &Q){
if(QueueEmpty(Q)){
printf("队列为空,无法出队!\n");
return FALSE;
}
else{
Q.front=(Q.front+1)%maxsize;
return Q.data[Q.front];
}
return 1;
}
void print()
{
int i,j;
printf("\n对应的邻接矩阵是:\n\n");
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
printf("%5d",G.arcs[i][j]);
printf("\n");
}
}
//邻接表构造无向图
void CreateDG()
{
int i,j,k;
ArcNode *s;
char ch,v1,v2;
printf("请输入顶点信息: ");
scanf("%c",&ch);
for(i=1;i<=n;i++)
{ MG[i]=getchar();
G.vexs[i] =g[i].data=i;
g[i].firstarc=NULL;
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
G.arcs[i][j]=0;
printf("输入边结点<v1 v2>信息:\n");
getchar();
for(k=1;k<=e;k++){
scanf("%c%c",&v1,&v2);
getchar();
j=Locate(v1);
i=Locate(v2);
s=(ArcNode *)malloc(sizeof(ArcNode));
s->adjvex=j;
s->nextarc=g[i].firstarc;
g[i].firstarc=s;
s=(ArcNode *)malloc(sizeof(ArcNode));
s->adjvex=i;
s->nextarc=g[j].firstarc;
g[j].firstarc=s;
G.arcs[i][j]=1;
G.arcs[j][i]=1;
}
}
void println(){
int i;
ArcNode *s;
printf("\n对应的邻接表是:\n");
for(i=1;i<=n;i++){
s=g[i].firstarc;
printf("%3c",MG[g[i].data]);
while(s!=NULL){
printf("%5d",s->adjvex);
s=s->nextarc;
}
printf("\n");
}
}
//邻接矩阵广度优先遍历
void BFS(int i){
int j;
int visited[maxsize]={0};
printf("%3c",MG[G.vexs[i]]);
visited[i]=TRUE;
EnQueue(Q,i);
while(!QueueEmpty(Q))
{
i=DeQueue(Q);
for(j=1;j<=n;j++)
if((G.arcs[i][j]==1)&&(!visited[j])){
printf("%3c",MG[G.vexs[j]]);
visited[j]=TRUE;
EnQueue(Q,j);
}
}
}
//邻接矩阵深度优先遍历
void DFS(int i){
int j;
static int visited[maxsize]={0};
printf("%3c",MG[G.vexs[i]]);
visited[i]=TRUE;
for(j=1;j<=n;j++)
if((G.arcs[i][j]==1)&&(!visited[j]))
DFS (j);
}
//邻接表的广度优先遍历
void BFSL(int k){
int i;
int visited[maxsize]={0};
ArcNode *p;
printf("%3c",MG[g[k].data]);
visited[k]=TRUE;
EnQueue(Q,k);
while(!QueueEmpty(Q)){
i=DeQueue(Q);
p=g[i].firstarc;
while(p!=NULL){
if(!visited[p->adjvex]){
printf("%3c",MG[g[p->adjvex].data]);
visited[p->adjvex]=TRUE;
EnQueue(Q,p->adjvex);
}
p=p->nextarc;
}
}
}
//邻接表的深度优先遍历
void DFSL(int k){
int j;
ArcNode *p;
static int visited[maxsize]={0};
printf("%3c",MG[g[k].data]);
visited[k]=TRUE;
p=g[k].firstarc;
while(p){
j=p->adjvex;
if(!visited[j])
DFSL(j);
p=p->nextarc;
}
}
void main()
{
int i,k,ch;char v;
printf("1.邻接表无向图\n");
printf("2.邻接表广度优先遍历\n");
printf("3.邻接表深度优先遍历\n");
printf("4.邻接矩阵\n");
printf("5.邻接矩阵广度优先遍历\n");
printf("6.邻接矩阵深度优先遍历\n");
printf("7.退出程序\n");
printf("输入结点及边的数目:\n");
scanf("%d %d",&n,&e);
while(1){
printf("\n输入选择: ");
scanf("%d",&ch);
switch(ch){
case 1:
CreateDG();
println();
break;
case 2:
printf("\n邻接表广度优先遍历后得到的序列是:\n ");
printf("从哪个结点开始: ");
getchar();
scanf("%c",&v);
BFSL(Locate(v));
break;
case 3:
printf("\n邻接表深度优先遍历后得到的序列是:\n ");
printf("从哪个结点开始: ");
getchar();
scanf("%c",&v);
DFSL(Locate(v));
break;
case 4:
print();
break;
case 5:
printf("\n邻接矩阵广度优先遍历后得到的序列是: \n");
printf("从哪个结点开始: ");
getchar();
scanf("%c",&v);
BFS(Locate(v));
break;
case 6:
printf("\n邻接矩阵深度优先遍历后得到的序列是:\n ");
printf("从哪个结点开始: ");
getchar();
scanf("%c",&v);
DFS(Locate(v));
break;
case 7:exit (0);
}
}
}