C语言邻接表——广度优先遍历,深度优先遍历

#include<stdio.h>
#include<stdlib.h>
#define MaxVertices 100
typedef char DataType;
//建立边表
typedef struct node
{
	int adjvex;				//指向边表结点
	struct node *nextarc;	//指向下一条边,没有则为NULL
	int info;				//权值
}ArcNode;
//建立顶点表
typedef struct
{
	DataType data[MaxVertices];			//顶点数据
	ArcNode *firstarc;		//指向该顶点的第一个边表结点
}VerNode;
//建立图
typedef struct
{
	VerNode adjlist[MaxVertices];//顶点数组
	int n;						 //总顶点的个数
	int e;						 //总的边数
}ALGraph;

//建立邻接表
void CrateGraph(ALGraph *G)
{
	int i, k;
	int v1, v2;									//输入的两个边
	int weight;											//权值
	printf_s("请输入邻接表的总顶点数和边数:");
	scanf_s("%d %d", &G->n, &G->e);
	fflush(stdin);
	printf_s("请输入顶点(回车结束一个输入)\n");
	for (i = 0; i < G->n; i++)
	{
		gets_s(G->adjlist[i].data, MaxVertices);
		G->adjlist[i].firstarc = NULL;					//初始化边头没有连接的边表
	}
	printf_s("请根据顶点的位置从1开始输入两两相邻的边和权值(中间用空格隔开)\n");
	for (k = 0; k < G->e; k++)
	{
		fflush(stdin);
		printf_s("第%d个连接点:", k + 1);
		scanf_s("%d %d %d", &v1, &v2, &weight);			//输入相邻的边和权值
		v1--; v2--;										//按顶点排序从1开始,减去1方便数组计算
		ArcNode *s = (ArcNode *)malloc(sizeof(ArcNode));
		s->info = weight;
		s->adjvex = v2;
		s->nextarc = G->adjlist[v1].firstarc;
		G->adjlist[v1].firstarc = s;

		s = (ArcNode *)malloc(sizeof(ArcNode));//加上后为无向输入
		s->adjvex = v1;
		s->info = weight;
		s->nextarc = G->adjlist[v2].firstarc;
		G->adjlist[v2].firstarc = s;
		/*s->nextarc = NULL;								//尾插法
		ArcNode *p;
		p = G->adjlist[v1].firstarc;
		if (p == NULL)
		{
		G->adjlist[v1].firstarc = s;
		}
		else
		{
		while (p->nextarc)
		{
		p = p->nextarc;
		}
		p->nextarc = s;
		}*/

	}
}
//打印邻接表
void DisGraph(ALGraph *G)
{
	int i;
	printf_s("序号\t顶点名称\t\t边表\n");
	for (i = 0; i < G->n; i++)
	{
		printf_s("%d\t", i + 1);						//打印序号
		printf_s("%s\t\t->", G->adjlist[i].data);		//打印顶点
		while (G->adjlist[i].firstarc)
		{
			printf_s("%d(%d)->", G->adjlist[i].firstarc->adjvex + 1, G->adjlist[i].firstarc->info);
			G->adjlist[i].firstarc = G->adjlist[i].firstarc->nextarc;
		}
		printf_s("NULL\n");
	}
}

//广度优先遍历
int visited[MaxVertices];
typedef struct LoopQueue
{
	int data[MaxVertices];
	int front;
	int rear;
}Queue, *LQueue;
void InitQueue(LQueue Q){  //初始化队列 
	Q->front = Q->rear = 0;
}
int QueueisFull(LQueue Q){ //判断队列是否满了 
	if ((Q->rear + 1) % MaxVertices == Q->front){
		return -1;  //已满 
	}
	else{
		return 1;
	}
}
int QueueisEmpty(LQueue Q){//判断队列是否为空 
	if (Q->front == Q->rear){
		return -1;
	}
	return 1;
}
void EnQueue(LQueue Q, int i){ //入队列 
	if (!QueueisFull(Q)){
		Q->data[Q->rear] = i;
		Q->rear = (Q->rear + 1) % MaxVertices;  //队尾指针后移 
	}
}
void DeQueue(LQueue Q, int *k){ //出队列 
	if (!QueueisEmpty(Q)){
		*k = Q->data[Q->front];
		Q->front = (Q->front + 1) % MaxVertices;
	}
}
void BFS(ALGraph *G)
{

	Queue Q;
	for (int i = 0; i < G->n; i++)
	{
		visited[i] = 0;
	}
	InitQueue(&Q);														 //初始化队列 
	for (int i = 0; i < G->n; i++)
	{
		visited[i] = 1;
		printf("%s ", G->adjlist[i].data);
		EnQueue(&Q, i);
		while (!QueueisEmpty(&Q))
		{
			DeQueue(&Q, &i);												 //这里不断的修改i的值!! 
			ArcNode *e = G->adjlist[i].firstarc;						 //i顶点的邻接链表的第一个结点
			while (e)
			{															//e存在时,将e的所有邻接点加入队列,也就是遍历i的所有邻接点 
				if (!visited[e->adjvex])
				{													    // adjvex是e所表示的结点下标 
					visited[e->adjvex] = 1;
					printf("\t%s", G->adjlist[e->adjvex].data);
					EnQueue(&Q, e->adjvex);							    //将该结点入队 
				}
				e = e->nextarc;											//遍历i的下一个邻接点 
			}
			printf_s("\n");
		}
	}
}
//深度优先遍历
int visited1[MaxVertices];
void DFS(ALGraph *G, int i)
{
	ArcNode *p;
	visited1[i] = 1;
	printf_s("%s ", G->adjlist[i].data);
	p = G->adjlist[i].firstarc;
	while (p)
	{
		if (!visited1[p->adjvex])
		{
			DFS(G, p->adjvex);
		}
		p = p->nextarc;
	}
}
void DFSTravel(ALGraph *G)
{
	int i;
	for (i = 0; i < G->n; i++)
	{
		visited1[i] = 0;
	}
	for (i = 0; i < G->n; i++)
	{
		if (!visited1[i])
		{
			DFS(G, i);
		}
	}
}
void main()
{
	ALGraph G;
	CrateGraph(&G);
	printf_s("\n");
	printf_s("广度优先遍历:");
	BFS(&G);
	printf_s("\n\n");
	printf_s("深度优先遍历:");
	DFSTravel(&G);
	printf_s("\n\n邻接表:\n");
	DisGraph(&G);
}

测试结果

  • 18
    点赞
  • 110
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

madkeyboard

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值