#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//全局定义特殊变量
#define MVNum 100
#define OVERFLOW 0
#define MAX 10
#define ok 1
//转定义区域
typedef int OtherInfo;
typedef char VerTexType;
typedef int status;
typedef int QElemType;
void Interrupt()//创建一个中断函数
{
while (1)//用于检测换行符,使函数脱离scanf的连续输出
if (getchar() == '\n')
break;
}
typedef struct ArcNode//边结点
{
int adjvex;//结点内容
struct ArcNode* nextarc;//下一条边
OtherInfo info;//权值(无向图用不到)
}ArcNode;
typedef struct VNode//顶点表
{
VerTexType data;
ArcNode* firstarc;
}VNode, AdjList[MVNum];
typedef struct
{
AdjList vertices;
int vexnum, arcnum;//vex指的是顶点,arc指的是边
}ALGraph;
typedef struct//定义循环队列
{
QElemType* base;
int front;
int rear;
}SqQueue;
status LocateVex(ALGraph& G, VerTexType V)//定位好顶点的位置
{
int i;
for(i=0;i<G.arcnum;i++)
{
if (V == G.vertices[i].data)
{
return i;
}
}
}
status CreateUDG(ALGraph& G)
{
int i,j,k;
printf("请输入该无向图的顶点数:");
scanf("%d",&G.vexnum);
printf("请输入该无向图的总边数:");
scanf("%d",&G.arcnum);
printf("请输入无向图的所有顶点:\n");
for (i = 0; i < G.vexnum; i++)//录入顶点
{
Interrupt();//放置前面才有用
printf("请输入第%d个顶点值:",i+1);
scanf("%c",&G.vertices[i].data);
G.vertices[i].firstarc = NULL;
}
for (k = 0; k < G.arcnum; k++)//输入各边构造邻接表
{
i=0;
VerTexType V1, V2;
ArcNode *p1, *p2;//两个边的野指针
Interrupt();
printf("请输入两个相连的顶点:\n");
printf("请输入第一个顶点:");
scanf("%c", &V1);
Interrupt();
printf("请输入第二个顶点:");
scanf("%c", &V2);
i = LocateVex(G, V1);//确定位置顶点的位置迁移至边
j = LocateVex(G, V2);
p1= (ArcNode*)malloc(sizeof(ArcNode));
p1->adjvex = j;
p1->nextarc = G.vertices[i].firstarc;//类似于链表的头插法
G.vertices[i].firstarc = p1;
p2 = (ArcNode*)malloc(sizeof(ArcNode));
p2->adjvex = i;
p2->nextarc = G.vertices[j].firstarc;
G.vertices[j].firstarc = p2;
}
return ok;
}
void DFS_AL(ALGraph G,int v,bool visited[])//深度优先遍历//v指的是顶点位置
{
int i, w;
ArcNode* p;
VerTexType V;
printf("->%d",v);
visited[v] = true;
p = G.vertices[v].firstarc;
while (p != NULL)
{
w = p->adjvex;
if (!visited[w])
{
DFS_AL(G, w, visited);
}
p = p->nextarc;
}
}
void Packfun_DFS(ALGraph G)//封装函数-DFS
{
int i,j;
bool visited[MVNum];
for (j = 0; j < G.vexnum; j++)
{
visited[j] = false;
}
VerTexType v;
Interrupt();
printf("请输入起始遍历的顶点:");
scanf("%c", &v);
i = LocateVex(G, v);
printf("%c:",v);
DFS_AL(G,i, visited);
}
status InitQueue(SqQueue& Q)//循环队列的初始化
{
Q.base = (QElemType*)malloc(sizeof(QElemType[MAX]));
if (!Q.base)
{
return OVERFLOW;
}
Q.front = Q.rear = 0;
return ok;
}
status EnQueue(SqQueue& Q, QElemType e)//入队
{
if ((Q.rear + 1) % MAX == Q.front)//队满的条件
{
return 0;
}
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % MAX;
return ok;
}
status QueueEmpty(SqQueue Q)//判断是否队空
{
if (Q.rear == Q.front)
{
return 1;
}
else
{
return 0;
}
}
status DeQueue(SqQueue& Q, QElemType& e)//出队
{
if (Q.rear == Q.front)//队空的条件
{
return 0;
}
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MAX;
return ok;
}
ArcNode* p;//创建一个全局变量,以便于进行查找
int FirstAdjVex(ALGraph G, int u)//表示u的第一个邻接点
{
p = G.vertices[u].firstarc;//全局变量的赋值
if (p == NULL)//如果头结点的下一个结点为空,返回负数,否则返回p结点的值
return -1;
else
return p->adjvex;
}
int NextAdjVex(ALGraph G)//下一个邻接点
{
p = p->nextarc;
if (p == NULL)
return -1;
else
return p->adjvex;
}
void BFS_AL(ALGraph G, int v, bool visited[])//广度优先遍历
{
int u;
printf("->%d", v);
visited[v] = true;
SqQueue Q;
InitQueue(Q);//引入队列,初始化
EnQueue(Q, v);//入队
while (!QueueEmpty(Q))//队列非空
{
DeQueue(Q,u);
for (int w = FirstAdjVex(G, u); w >= 0; w = NextAdjVex(G))
if (!visited[w])
{
printf("->%d", w);
visited[w] = true;
EnQueue(Q, w);//w入队
}
}
}
void Packfun_BFS(ALGraph G)//封装函数-BFS
{
int i,j;bool visited[MVNum];
for (j = 0; j < G.vexnum; j++)
{
visited[j] = false;
}
VerTexType v;
Interrupt();
printf("请输入起始遍历的顶点:");
scanf("%c", &v);
i = LocateVex(G, v);
printf("%c:", v);
BFS_AL(G, i, visited);
}
int main()
{
int a, f = 0, i = 0;
ALGraph G;
while (1)
{
printf("\n");
printf("================================\n");
printf("| 无向图操作系统 |\n");
printf("================================\n");
printf("| 1.无向图的录入 |\n");
printf("| 2.深度优先遍历 |\n");
printf("| 3.广度优先遍历 |\n");
printf("| 0.退出队列操作系统 |\n");
printf("================================\n");
printf("请选择功能(0-5):");
mark:scanf("%d", &a);
switch (a)
{
case 0:f = 1; break;
case 1: CreateUDG(G); break;
case 2: Packfun_DFS(G); break;
case 3: Packfun_BFS(G); break;
default:printf("选择功能错误!请重新选择菜单功能:"); goto mark;
}
if (f == 1)
{
printf("已经退出系统");
break;//该break是为了退出while的无限“菜单”循环
}
}
}
构建的无向图:
代码实施效果:
录入图:
遍历效果:
使用的编译环境是vs2019,源文件后缀是.cpp