输入图的类型、顶点数、狐(边)数、顶点信息、狐(边)信息,建立相应的图(具体类型为有向图、无向图,采用邻接矩阵存储结构);分别按深度优先搜索和广度优先搜索遍历图;按某种形式输出图及遍历结果
#include <stdio.h>
#include <stdlib.h>
#define OVERFLOW -2
#define ILLEGAL -1
#define OK 1
#define ERROR 0
#define MAXQSIZE 100 //队列的最大长度
typedef int QElemType;
typedef int Status;
typedef float ElemType;
//-------------图的数组(邻接矩阵)存储表示-------------------------------------
#define INFINITY 65535 //最大值 ∞
#define MAX_VERTEX_NUM 20 //最大顶点个数
typedef enum {DG,UDG} GraphKind; //(有向图,无向图)
typedef int VRType;
typedef int VertexType;
typedef struct ArcCell{
VRType adj; //VRType是顶点关系类型。对无权图,用1或0,表示相邻与否,对带权图,则为权值类型
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct{
VertexType vexs[MAX_VERTEX_NUM]; //顶点向量
AdjMatrix arcs; //邻接矩阵
int vexnum,arcnum; //图当前的定点数和弧数
GraphKind kind; //图的种类标志
}MGraph;
//------------------图的创建-------------------------------------------------------
int LocateVex(MGraph G, int v){ //顶点定位函数
for(int i=0; i<=G.vexnum; ++i)
if(G.vexs[i]==v)
return i; //若找到结点返回i
return -1; //否则返回-1,表示没有找到
}
Status CreateDG(MGraph &G){
//采用数组(邻接矩阵)表示法,构造有向图G
VertexType v1,v2;
int i,j;
printf("请依次输入有向图G的顶点数,弧数,用空格隔开\n");
scanf("%d %d",&G.vexnum,&G.arcnum);
printf("请依次输入有向图G的顶点名称,用空格隔开\n");
for(int i=0;i<G.vexnum;++i)
scanf("%d",&G.vexs[i]); //构造各顶点向量
for(int i=0;i<G.vexnum;++i)
for(int j=0;j<G.vexnum;++j)
G.arcs[i][j].adj=0;
printf("请依次输入有向图G每条弧依附的两顶点名称,输完一组按回车\n");
for(int k=0;k<G.arcnum;++k){ //构造邻接矩阵
scanf("%d",&v1);
scanf("%d",&v2);
i=LocateVex(G,v1);
j=LocateVex(G,v2); //确定v1,v2在G中的位置
G.arcs[i][j].adj=1;
}//for
return OK;
}
Status CreateUDG(MGraph &G){
//采用数组(邻接矩阵)表示法,构造无向图G
VertexType v1,v2;
int i,j;
printf("请依次输入无向图G的顶点数,弧数,用空格隔开\n");
scanf("%d %d",&G.vexnum,&G.arcnum);
printf("请依次输入无向图G的顶点名称,用空格隔开\n");
for(int i=0;i<G.vexnum;++i)
scanf("%d",&G.vexs[i]); //构造各顶点向量
for(int i=0;i<G.vexnum;++i)
for(int j=0;j<G.vexnum;++j) //预置邻接矩阵
G.arcs[i][j].adj=0;
printf("请依次输入无向图G每条弧依附的两顶点名称,输完一组按回车\n");
for(int k=0;k<G.arcnum;++k){ //构造邻接矩阵
scanf("%d",&v1);
scanf("%d",&v2);
i=LocateVex(G,v1);
j=LocateVex(G,v2); //确定v1,v2在G中的位置
G.arcs[i][j].adj=1;
G.arcs[j][i]=G.arcs[i][j]; //置<v1,v2>的对称弧<v2,v1>
}//for
return OK;
}
Status CreateGraph(MGraph &G){ //总函数
//采用数组(邻接矩阵)表示法,构造图G
printf("请输入您想构造的图的类型:有向图,无向图,分别对应0,1):");
int temp;
scanf("%d",&temp); //输入所要构造图的类型
G.kind=(GraphKind)temp;
switch((GraphKind)temp){
case DG: return CreateDG(G); //构造有向图G
case UDG: return CreateUDG(G); //构造无向图G
default : return ERROR;
}
}
//--------------------------邻接矩阵的输出 ----------------------------------------------
Status PrintAdjMatrix(MGraph G){ //打印某个图的邻接矩阵
//采用数组(邻接矩阵)表示法,构造图G
for(int i=0;i<G.vexnum;i++){
for(int j=0;j<G.vexnum;j++)
printf(" %3d ", G.arcs[i][j].adj);
printf("\n\n");
}
}
//------------------------------------3.图的遍历 ----------------------------------------------
int FirstAdjVex(MGraph G,VertexType v){
//求顶点v在图G中的第一个邻接点
int i,j=0,k;
k=LocateVex(G,v); //v是顶点,不是序号!需要定位
for(i=0;i<G.vexnum;++i)
if(G.arcs[k][i].adj!=j)
return i; //若找到则返回i
return -1; //若未找到返回-1
}//FirstAdjVex
int NextAdjVex(MGraph G,VertexType v,VertexType w){
//求顶点v在图G中相对于邻接点w的下一个邻接点
int i,j=0,k1,k2;
k1=LocateVex(G,v); //v是顶点,不是序号!需要定位
k2=LocateVex(G,w); //w是顶点,不是序号!需要定位
for(i=k2+1;i<G.vexnum;++i)
if(G.arcs[k1][i].adj!=j)
return i; //若找到则返回i
return -1; //若未找到返回-1
}//NextAdjVex
//-----------------------深度优先遍历DFS-----------------------------
typedef enum { TRUE=1 , FALSE=0 } Boolean;
Boolean visited[MAX_VERTEX_NUM]; //访问标志数组
Status (*VisitFunc)(int v); //函数变量
Status Print(int v){ //元素访问函数
printf(" %3d ",v);
return OK;
}//Print
void DFSTraverse(MGraph G,Status (*Visit)(int v)){
//对图G作深度优先遍历,调用Visit()函数访问结点
void DFS(MGraph G,int v); //函数声明
VisitFunc=Visit; //使用全局变量VisitFunc,使DFS不必设函数指针参数
for(int v=0;v<G.vexnum;++v)
visited[v]=FALSE; //预置标志数组
for(int v=0;v<G.vexnum;++v)
if(!visited[v]) //若该顶点未被访问
DFS(G,v);
}//DFSTraverse
void DFS(MGraph G,int v){
//从第v个顶点出发递归地深度优先遍历图G
visited[v]=TRUE; //先将访问标志数组该元素的访问标志改为True
//注意,序号v从0开始,所以序号v总比第v个顶点在图中的位置少1
VisitFunc(G.vexs[v]); //访问第v个顶点 注意:v是序号,不是顶点!
for(int w=FirstAdjVex(G,G.vexs[v]);w>=0;w=NextAdjVex(G,G.vexs[v],G.vexs[w])){ //v是序号,不是顶点!
if(!visited[w])
DFS(G,w); //对v的尚未访问的邻接点w递归调用DFS
}//for
}//DFS
//------------------------广度优先遍历(BFS)----------------------------------------
//-------------------循环队列----------------------------------------
typedef struct //循环队列的C语言描述
{
QElemType *base; //初始化动态分配存储空间
int front; //头指针,若队列不空,指向队头元素
int rear; //尾指针,若队列不空,指向队尾元素的下一个位置
}SqQueue;
//>>>>>>>>>>>>>>>>>>>>1.初始化循环队列<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Status InitQueue_Sq(SqQueue &Q) //初始化循环队列
{ //构建一个空队列 Q
if(!(Q.base=(QElemType *)malloc(sizeof(QElemType)))){ //申请内存空间,若失败则提示并退出程序
printf("内存分配失败,程序即将退出!\n");
exit(OVERFLOW);
}
Q.front=Q.rear=0;
return OK;
}
//>>>>>>>>>>>>>>>>>>>2.销毁循环队列<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Status DestoryQueue_Sq(SqQueue &Q)
{ //销毁队列Q
free(Q.base);
Q.base=NULL;
printf("循环队列已成功销毁!\n");
return OK;
}
//>>>>>>>>>>>>>>>>>>>3.判断链队列是否为空<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Status QueueEmpty_Sq(SqQueue Q)
{ //若Q为空队列,则返回OK;否则返回ERROR
if(Q.rear==Q.front) //队列为空的标志
return OK;
else
return ERROR;
}
//>>>>>>>>>>>>>>>>>>>4.在链队列中插入元素(入队)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Status EnQueue_Sq(SqQueue &Q,QElemType e)
{ //插入元素e为Q的新的队尾元素e
if((Q.rear+1)%MAXQSIZE==Q.front) //队列满
return ERROR;
Q.base[Q.rear]=e;
Q.rear=(Q.rear+1)%MAXQSIZE; //每插入一个新队尾元素,尾指针增一
return OK;
}
//>>>>>>>>>>>>>>>>>>5.在链队列中删除元素(出队)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Status DeQueue_Sq(SqQueue &Q,QElemType &e)
{ //若队列不空,则删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR
if(Q.front==Q.rear) //判空
return ERROR;
e=Q.base[Q.front];
Q.front=(Q.front+1)%MAXQSIZE; //每当删除队头元素时,头指针增1
return OK;
}
void BFSTraverse(MGraph G,Status (*Visit)(int v)){
//按广度优先非递归遍历图G,使用辅助队列Q和访问标志数组visited
SqQueue Q;
for(int v=0;v<G.vexnum;++v)
visited[v]=FALSE; //预置标志数组
InitQueue_Sq(Q); //置空辅助队列Q
for(int v=0;v<G.vexnum;++v)
if(!visited[v]){ //v尚未访问
visited[v]=TRUE;
Visit(G.vexs[v]); //访问第v顶点
EnQueue_Sq(Q,v); //v入队列
while(!QueueEmpty_Sq(Q)){ //队列不空
DeQueue_Sq(Q,v); //队头元素出队并置为u
for(int w=FirstAdjVex(G,G.vexs[v]);w>=0;w=NextAdjVex(G,G.vexs[v],G.vexs[w])){
if(!visited[w]){ //w为v尚未访问的邻接顶点
visited[w]=TRUE;
Visit(G.vexs[w]); //访问第w顶点
}//if
}//for
}//while
}//if
}//BFSTraverse
//-------------------------------主函数-------------------------------
int main(int argc,char *argv[]){
MGraph G;
CreateGraph(G); //图的创建
printf(" 图的邻接矩阵:\n\n");
PrintAdjMatrix(G); //打印邻接矩阵
printf("图的遍历:\n");
printf("深度优先遍历结果:");
DFSTraverse(G,Print);
printf("\n广度优先遍历结果:");
BFSTraverse(G,Print);
return 0;
}