程序实现的功能:
1、编写为从键盘输入的数据建立图的邻接表存储
2、编写图的深度优先遍历程序
3、编写图的广度优先遍历程序
4、设计选择菜单,以选择菜单方式进行操作。
queue.h:
#define MAXQSIZE 31
#define qelemtype int
#define OVERFLOW -1
#define OK 1
#define ERROR 0
typedef struct{
qelemtype *base;//队列基准地址
int front;//头部
int rear;//尾部
}sqqueue;
void initqueue(sqqueue *q){ //创建队列
q->base = (qelemtype *)malloc(MAXQSIZE*sizeof(qelemtype));
if(!q->base){
exit(OVERFLOW);
}
q->front = q->rear = 0;
}
int enqueue(sqqueue *q,qelemtype e){ //添加队列节点
if((q->rear + 1) % MAXQSIZE == q->front){
return(ERROR);
}
q->base[q->rear] = e;
q->rear = (q->rear + 1) % MAXQSIZE;
return OK;
}
int dequeue(sqqueue *q,qelemtype *e){ //移出队列节点
if(q->front == q->rear)
{
return ERROR;
}
*e = q->base[q->front];
q->front = (q->front + 1) % MAXQSIZE;
return OK;
}
int queueempty(sqqueue q){ //判断队列是否为空
if(q.front == q.rear)
{
return OK;
}
else
{
return ERROR;
}
}
main.cpp:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"queue.h"
#define VertexType char
#define GraphKind char
//DG,DN,UDG,UDN分别表示 有向图,有向网,无向图,无向网
typedef struct ArcNode{
int adjvex;//边节点
struct ArcNode *nextarc;//下一个边节点
}ArcNode; //邻接表节点
typedef struct VNode{
VertexType vexdata;//顶点
ArcNode *firstarc;//边
}VNode; //邻接表结结构
typedef struct{
VNode *vertices;//vertices为vertex的复数,指向顶点【但由于是指针形式,所以可以当作数组基准地址】
int vexnum;//定点数
int arcnum;//边数
GraphKind kind[4];//图的种类
}ALGraph; //图结构
void visit(VNode v){ //打印图节点
printf("%c ",v.vexdata);
}
int LocateVex(ALGraph *a,char ch){ //查找图节点
int i = 0;//用于for循环
for(;i < a->vexnum;++i){//遍历所有节点
if(a->vertices[i].vexdata == ch){//如果某个节点数值等于查找值
return i;//返回节点序号i
}
}
exit(-1);//否则返回错误
}
void CreateGraph(ALGraph *a){ //建图
printf("请输入图类,顶点数和边数:");
scanf("%s",&a->kind[0]);//%[^ ]s表示输入非空字符串,存在kind数组中【4位长度】
// getchar();
scanf("%d%d",&a->vexnum,&a->arcnum);//定点数和边数
getchar();
a->vertices = (VNode*)malloc(a->vexnum * sizeof(VNode));//足够的节点分配空间
printf("请输入顶点:");
int i = 0;//用于for循环
for(;i < a->vexnum;++i){//遍历所有节点 来做初始化
scanf("%c",&(a->vertices[i].vexdata));
getchar();
a->vertices[i].firstarc = NULL;//边先全部设置为null
}
printf("请输入各边:");
i = 0;//用于for循环
for(;i < a->arcnum;++i){//遍历所有边
char sv,tv;//两个字符用于接收边
scanf("%c%c",&sv,&tv);
getchar();
int j = LocateVex(a,sv);//用查找定位到sv节点位置
int k = LocateVex(a,tv);//用查找定位到tv节点位置
ArcNode *p = (ArcNode*)malloc(sizeof(ArcNode));//创建一个边节点并且分配内存空间
//使用头插法
p->adjvex = k;//先把边取成k
p->nextarc = a->vertices[j].firstarc;//指向首个边节点
a->vertices[j].firstarc = p;//再将首个边节点指向p
if(a->kind[0] == 'U'&&a->kind[1] == 'D'){//如果是无向图
ArcNode *q = (ArcNode*)malloc(sizeof(ArcNode));//创建新节点q,对另一部分做类似操作
q->adjvex = j;
q->nextarc = a->vertices[k].firstarc;
a->vertices[k].firstarc = q;
}
}
}
void DFS(ALGraph a,int *sign,int v,void (*visit)(VNode v)){ //连通图深度优先遍历
sign[v] = 1;//先把当前节点访问成功
visit(a.vertices[v]);//访问当前节点
ArcNode *p = a.vertices[v].firstarc;//用于for循环
for(;p != NULL;p = p->nextarc){//遍历p的所有相连的节点
if(!sign[p->adjvex]){//只要未被访问则被重新访问
DFS(a,sign,p->adjvex,visit);//传入下一个节点 p->adjvex
}
}
}
void DFSTraverse(ALGraph a,void (*visit)(VNode v)){ //非连通图深度优先遍历
int sign[a.vexnum];//定义标记数组
memset(sign,0,sizeof(sign)); //清空数组
int v = 0;
for(;v < a.vexnum;++v){//遍历全部的节点
if(!sign[v]){//如果这个节点还没被标记,则对其进行DFS
DFS(a,sign,v,visit);
}
}
}
void BFS(ALGraph a,int *sign,int v,sqqueue *q,void (*visit)(VNode v)){ //连通图广度优先遍历
sign[v] = 1;//先把当前节点访问成功
visit(a.vertices[v]);//访问当前节点
enqueue(q,v);//当前节点入队
for(;queueempty(*q) != 1;){//只要队列不空
int w;//定义w用来储存出队的元素
dequeue(q,&w);//出队
ArcNode *p = a.vertices[w].firstarc;//定义p指向w的邻接节点 的首节点
for(;p != NULL;p = p->nextarc){ //遍历w邻接节点
if(sign[p->adjvex] == 0){//只要未被访问
sign[p->adjvex] = 1;//标记访问
enqueue(q,p->adjvex);//入队
visit(a.vertices[p->adjvex]);//访问
}
}
}
}
void BFSTraverse(ALGraph a,void (*visit)(VNode v)){ //非连通图广度优先遍历
int sign[a.vexnum];//定义标记数组
memset(sign,0,sizeof(sign)); //清空数组
sqqueue q;//创建一个辅助队列,用于广度优先
initqueue(&q); //队列初始化
int v = 0;
for(;v < a.vexnum;++v){//遍历全部的节点
if(!sign[v]){
BFS(a,sign,v,&q,visit);//如果这个节点还没被标记,则对其进行BFS
}
}
}
int main(){
ALGraph UDG;//先创建无向图
for(;;){
printf("\n请选择 1.建立图 2.深度优先遍历图 3.广度优先遍历图 0.结束:\n");
int n;//用于接收输入
scanf("%d",&n);
// getchar();
switch(n){
case 1:{
CreateGraph(&UDG);//创建无向图
printf("建立成功。\n");
break;
}
case 2:{
DFSTraverse(UDG,visit);//深度优先遍历
printf("\n深度优先遍历成功。\n");
break;
}
case 3:{
BFSTraverse(UDG,visit);
printf("\n广度优先遍历成功。\n");
break;
}
case 0:
return 0;
break;
default:{
printf("你输入的请求不符合规范,请重新输入!\n");
break;
}
}
}
}
运行结果截图: