无向图的深度与广度优先遍历

#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 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值