一、编写程序任意输入顶点个数、顶点信息、以及边或弧的信息,构造对应的有向图或无向图,生成图的bfs以及dfs遍历序列,并验证是否正确。
①采用不同的图生成相应的遍历序列,并分析其内部存储结构的实现。
②试分析:邻接表中邻接点的链表编号创建顺序与用户输入的先后顺序有何关联,对深度优先遍历序列以及广度优先遍历序列有何影响。
先输入的后出来。
#include "malloc.h"
#include <stdio.h>
#include <iostream.h>
#define maxvertexnum 20
#define queuesize 20
#define NULL 0
typedef struct
{ int front;
int rear;
int count;
int data[queuesize];
}cirqueue;
//循环队列结构定义
typedef char vertextype;//为了简单,设图中结点的数据为字符型
typedef struct node{
int adjvex; //存放邻接点序号
struct node *next;//指向下一个边结点
}edgenode;//图的邻接表的边结点定义
typedef struct vnode{
vertextype vertex; //顶点数据域
edgenode *firstedge; //指向第一个边结点
} vertexnode; //图的邻接表表示的顶点结点定义
typedef vertexnode adjlist[maxvertexnum];//用向量定义图的邻接表表示的顶点表
typedef struct{
adjlist adjlist;
int n;//图的顶点数
int e;//图的边数
}algraph;//定义图的邻接表
typedef enum{FALSE,TRUE}boolean;
boolean visited[maxvertexnum];//保存访问信息的布尔向量
void createalgraph(algraph &g)
{//建立图g的邻接表表示
int i,j,k;
int flag;
edgenode *s;
cout<<"creat: digraph--0(0表示有向图)"<<"undigraph--1(1表示无向图)";//选择建立有向图或无向图
cin>>flag;//0表示有向图,1表示无向图
cout<<"input (顶点数)n:";
cin>>g.n;//输入图g的顶点数
cout<<"input (边或弧的数目)e:";
cin>>g.e;//输入图g的边数
cout<<"input nodes(顶点的数据域——单个字符符号):";
for(i=1;i<=g.n;i++){//构造一个只含n个顶点,边数为0的图
cin>>g.adjlist[i].vertex;//输入顶点的数据域(为了简单起见,输入为单个字符)
g.adjlist[i].firstedge=NULL;//将顶点结点的firstedge域置为空
}//end for
for(k=1;k<=g.e;k++){
cout<<"input i,j(边的信息序偶对如:1 2):";
cin>>i>>j;//输入对应于一条边的顶点序号序偶对,要求顶点序号为1~n
s=(edgenode *)malloc(sizeof(edgenode));//申请一个边结点*s
s->adjvex=j;//将序号j放入边结点*s的adjvex域
s->next=g.adjlist[i].firstedge;//将边结点*s作为第一个邻接点插入到序号为i的顶点的边表中
g.adjlist[i].firstedge=s;
if (flag){//若要建立无向图
s=(edgenode *)malloc(sizeof(edgenode));//申请一个边结点*s
s->adjvex=i;//将序号i放入边结点*s的adjvex域
s->next=g.adjlist[j].firstedge;
//将边结点*s作为第一个邻接点插入到序号为j的顶点的边表中
g.adjlist[j].firstedge=s;
}//end of if
}//end of for
}//end of creatalgraph
void dfs(algraph g,int i)
{//对图g进行以序号为i的顶点作为出发点深度优先搜索
edgenode *p;
cout<<g.adjlist[i].vertex<<" ";//打印序号为i的顶点信息
visited[i]=TRUE;//将序号为i的顶点设置已访问过标记
p=g.adjlist[i].firstedge;//设置寻找序号为i的第一个未访问过邻接点的扫描指针
while(p){
if (!visited[p->adjvex])//若*p边结点对应顶点(假设序号为j)未访问过
dfs(g,p->adjvex);//对图g进行以序号为j的顶点作为出发点进行深度优先搜索
p=p->next;//p顺着边表next指针,往后继续寻找
}//end of while
}//end of dfs
void dfstraverse(algraph g)
{//对以邻接表表示的图g进行深度优先搜索
int i;
for(i=1;i<=g.n;i++)//将图g的所有顶点设置未访问过标记
visited[i]=FALSE;
// printf("dfs visit vertex:");
for(i=1;i<=g.n;i++)//对图g调用dfs函数进行深度优先搜索
if(!visited[i])
dfs(g,i);
printf("\n");
}//end of dfstraverse
void bfs(algraph g,int k)
{//对图g进行以序号为k的顶点作为出发点广度优先搜索
int i;
cirqueue *q;//设置循环队列指针
edgenode *p;
q=(cirqueue *)malloc(sizeof(cirqueue));//申请循环队列空间
q->rear=q->front=q->count=0;//将循环队列置为空队
cout<<g.adjlist[k].vertex<<" ";
visited[k]=TRUE;//将序号为k的顶点设置为已访问过
q->data[q->rear]=k;q->rear=(q->rear+1)%queuesize;q->count++;//将顶点序号k入队
while(q->count){//当队列非空时做以下操作
i=q->data[q->front];q->front=(q->front+1)%queuesize;q->count--;//将队首元素i出队
p=g.adjlist[i].firstedge;//设置寻找序号为i顶点的未访问过邻接点的扫描指针p
while (p){//当*p不为空时,做以下操作
if(!visited[p->adjvex]){//若*p边结点对应顶点(假设序号为j)未访问过
cout<<g.adjlist[p->adjvex].vertex<<" ";
//访问序号为j的顶点
visited[p->adjvex]=TRUE;//设置已访问过标记
q->data[q->rear]=p->adjvex;q->rear=(q->rear+1)%queuesize;q->count++;
//将序号为j的顶点入队
}//end of if
p=p->next;//p顺着边表next指针,往后继续寻找
}//end of while
}//end of while
}//end of bfs
void bfstraverse(algraph g)
{//对以邻接表表示的图g进行广度优先搜索
int i;
for(i=1;i<=g.n;i++)//将图g的所有顶点设置未访问过标记
visited[i]=FALSE;
// printf("bfs visit vertex:");
for(i=1;i<=g.n;i++)//对图g调用bfs函数进行广度优先搜索
if(!visited[i])
bfs(g,i);
cout<<endl;
}
main()//主函数
{//建立图g,并进行深度优先搜索和广度优先搜索
algraph g;
createalgraph(g);//建立图g的邻接表表示
cout<<"the dfs is:"<<" ";
dfstraverse(g);//对图g进行深度优先搜索,并打印搜索序列
cout<<endl;
cout<<"the bfs is:"<<" ";
bfstraverse(g);//对图g进行广度优先搜索,并打印搜索序列
}
例:
图的形状如下图示: