数据结构 c语言实现图的邻接表创建及深度与广度优先遍历

这里将顶点通过数组的方式写入,直接输入边的数量,顶点信息和权值,如果要更改数组元素的数量则也需要修改最多顶点数,以及标记数组的元素的数量,并将其初始化为1,这里太懒了不想弄。

 

#include <stdio.h>
#include <stdlib.h>
#define MVNUM 5 //最多的顶点数
typedef char VerTexType; //顶点元素的类型
VerTexType vexs[MVNUM]={'a','b','c','d','e'}; //顶点数组
int visited[5]={0,0,0,0,0};  //深度and广度优先遍历的标记数组
typedef struct ArcNode //边节点
{
	int adjvex,info;  //adjvex该边所指向的顶点的位置  info和边相关的信息
	struct ArcNode *nextarc;  //指向下一条边的指针
}ArcNode;
typedef struct VNode //顶点数组
{
	VerTexType data;  //顶点信息
	struct ArcNode *firstarc;  //指向第一条依附该顶点的边的指针
}VNode,AdjList[MVNUM]; //AdjList表示邻接表的类型
typedef struct  //ALGraph定义
{
	AdjList vertices;  //顶点数组
	int vexnum,arcnum; //图当前的顶点数和弧数
}ALGraph;
typedef struct  //定义广度优先遍历的辅助队列
{
	int data[MVNUM]; 
	int front,rear;
}SqQueue;

//函数声明
void InitALGraph(ALGraph *G,VerTexType vex[],int len);  //初始化图
ArcNode *CreateArcNode(int adjvex,int info);  //生成ArcNode也就是边的结点
int FindVexIndex(ALGraph *G,VerTexType v,int len);
void DFS(ALGraph *G,int v);  //深度优先遍历
void BFS(ALGraph *G,int v);  //广度优先遍历
void InitSqQueue(SqQueue *Q); //初始化队列
void EnQueue(SqQueue *Q,int v);//入队
int QueueEmpty(SqQueue *Q); //判断队列是否为空
void DeQueue(SqQueue *Q,int *u); //出队
int main()
{
	ALGraph G;
	int i=0;
	InitALGraph(&G,vexs,MVNUM);
	printf("顶点元素:\n");
	for(i=0;i<MVNUM;i++)
	{
		printf("%c ",G.vertices[i].data);
	}
	printf("\n");
	printf("\n深度优先遍历:\n");
	DFS(&G,2); //这里0的是顶点的下标
	for(i=0;i<MVNUM;i++)  //这里因为深度优先遍历标记过了,所以重新初始化为0
	{
		visited[i]=0;
	}
	printf("\n");
	printf("\n广度优先遍历:\n");
	BFS(&G,1);
	printf("\n");


}
void InitALGraph(ALGraph *G,VerTexType vex[],int len)  //初始化图
{
	int i,j,k,w;
	char v1=' ',v2=' ';
	G->vexnum=len;
	printf("请输入边的数量:\t");
	scanf("%d",&G->arcnum);
	for(i=0;i<len;i++)
	{
		G->vertices[i].data=vex[i];
		G->vertices[i].firstarc=NULL;
	}
	for(k=0;k<G->arcnum;k++)
	{
		ArcNode *p1,*p2;
		printf("第条%d边邻接的顶点以及权值,输入是请用空格格开  ###格式为:a b 5\n",k+1);
		scanf(" %c %c %d",&v1,&v2,&w);
		i=FindVexIndex(G,v1,len);
		j=FindVexIndex(G,v2,len);
		p1=CreateArcNode(j,w);  //有向网的邻接表,只需将p2的代码注释即可 把p1注释 便是逆邻接表
		p2=CreateArcNode(i,w);  
		p1->nextarc=G->vertices[i].firstarc;
		G->vertices[i].firstarc=p1;
		p2->nextarc=G->vertices[j].firstarc;
		G->vertices[j].firstarc=p2;
	}
}
int FindVexIndex(ALGraph *G,VerTexType v,int len)  //找到v的下标
{
	int i=0;
	for(i=0;i<len;i++)
	{
		if(G->vertices[i].data==v)return i;
	}
	return -1;
}
ArcNode *CreateArcNode(int adjvex,int info)  //生成ArcNode也就是边的结点
{
	ArcNode *newNode=(ArcNode*)malloc(sizeof(ArcNode));
	newNode->adjvex=adjvex;
	newNode->info=info;
	newNode->nextarc=NULL;
	return newNode;
}
void DFS(ALGraph *G,int v)  //深度优先遍历
{
	ArcNode *p;
	printf("%c	",G->vertices[v].data);
	visited[v]=1;
	p=G->vertices[v].firstarc;
	while(p!=NULL)
	{
		if(visited[p->adjvex]==0)
		{
			DFS(G,p->adjvex);
		}
		p=p->nextarc;
	}
}
void BFS(ALGraph *G,int v) //广度优先遍历
{
	int u;
	SqQueue Q;
	ArcNode *p;
	visited[v]=1;
	printf("%c	",G->vertices[v].data);
	InitSqQueue(&Q);
	EnQueue(&Q,v);
	while(Q.front!=Q.rear)
	{
		DeQueue(&Q,&u);
		p=G->vertices[u].firstarc;
		while(p!=NULL)
		{
			if(visited[p->adjvex]==0)
			{
				printf("%c	",G->vertices[p->adjvex]);
				visited[p->adjvex]=1;
				EnQueue(&Q,p->adjvex);
			}
			p=p->nextarc;
		}
	}

}
void InitSqQueue(SqQueue *Q)  //初始化队列
{
	Q->front=Q->rear=0;
}
void EnQueue(SqQueue *Q,int v)  //入队
{
	Q->data[Q->rear]=v;
	Q->rear=(Q->rear+1)%MVNUM;
	
}
int QueueEmpty(SqQueue *Q)  //判断队列是否为空
{
	if(Q->front==Q->rear){
		return 1;
	}
	return 0;
}
void DeQueue(SqQueue *Q,int *u) //出队
{
	*u=Q->data[Q->front];
	Q->front=(Q->front+1)%MVNUM;
}

  • 2
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 邻接表是用于存储数据结构深度优先遍历广度优先遍历是两种常见的遍历算法。 下面是C语言实现邻接表深度优先遍历广度优先遍历的代码: 首先,定义邻接表的结构体: ```c typedef struct EdgeNode { int adjvex; // 邻接点下标 struct EdgeNode *next; // 指向下一个邻接点的指针 } EdgeNode; typedef struct VertexNode { int data; // 顶点数据 EdgeNode *firstedge; // 指向第一个邻接点的指针 } VertexNode, AdjList[MAXV]; typedef struct { AdjList adjList; // 邻接表 int vexnum, edgenum; // 顶点数和边数 } GraphAdjList; ``` 然后,实现深度优先遍历: ```c // 访问顶点 v void visit(int v) { printf("%d ", v); } // 从顶点 v 开始深度优先遍历 void DFS(GraphAdjList G, int v, int visited[]) { visited[v] = 1; // 标记顶点 v 已被访问 visit(v); // 访问顶点 v EdgeNode *p = G.adjList[v].firstedge; while (p != NULL) { int w = p->adjvex; // 获取邻接点下标 if (!visited[w]) { // 若邻接点未被访问,则递归访问它 DFS(G, w, visited); } p = p->next; } } // 遍历整个,对每个未被访问的顶点调用 DFS void DFSTraverse(GraphAdjList G) { int visited[MAXV] = {0}; // 初始化 visited 数组为 0 for (int i = 0; i < G.vexnum; i++) { if (!visited[i]) { DFS(G, i, visited); } } } ``` 最后,实现广度优先遍历: ```c // 从顶点 v 开始广度优先遍历 void BFS(GraphAdjList G, int v, int visited[]) { int queue[MAXV], front = 0, rear = 0; visit(v); // 访问顶点 v visited[v] = 1; // 标记顶点 v 已被访问 queue[rear++] = v; // v 入队 while (front != rear) { // 队列非空 int w = queue[front++]; // 出队 EdgeNode *p = G.adjList[w].firstedge; while (p != NULL) { int u = p->adjvex; // 获取邻接点下标 if (!visited[u]) { // 若邻接点未被访问,则访问它并将其入队 visit(u); visited[u] = 1; queue[rear++] = u; } p = p->next; } } } // 遍历整个,对每个未被访问的顶点调用 BFS void BFSTraverse(GraphAdjList G) { int visited[MAXV] = {0}; // 初始化 visited 数组为 0 for (int i = 0; i < G.vexnum; i++) { if (!visited[i]) { BFS(G, i, visited); } } } ``` 其中,MAXV 表示最大顶点数。 ### 回答2: 邻接表是一种存储结构C语言可以通过链表来实现邻接表深度优先遍历广度优先遍历深度优先遍历深度优先遍历是一种以深度优先的遍历方法,它从起始顶点开始,访问其所有未访问过的邻接顶点,然后再访问这些邻接顶点的邻接顶点。在C语言中,我们可以使用递归函数来实现深度优先遍历邻接表。具体步骤如下: 1. 创建一个数组visited,用于记录每个顶点是否被访问过。 2. 选择一个起始顶点v,将visited[v]标记为已访问。 3. 遍历顶点v的邻接链表,对于每个未访问过的邻接顶点u,调用递归函数DFS(u),继续深度优先遍历。 4. 重复步骤3,直到中所有的顶点都被访问过。 具体的C语言代码如下: ``` #include <stdlib.h> #include <stdio.h> struct Node { int data; struct Node* next; }; void DFS(int v, struct Node** adj_list, int* visited) { struct Node* temp = adj_list[v]; visited[v] = 1; printf("%d ", v); while (temp != NULL) { int u = temp->data; if (!visited[u]) { DFS(u, adj_list, visited); } temp = temp->next; } } void addEdge(struct Node** adj_list, int src, int dest) { struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); newNode->data = dest; newNode->next = adj_list[src]; adj_list[src] = newNode; newNode = (struct Node*)malloc(sizeof(struct Node)); newNode->data = src; newNode->next = adj_list[dest]; adj_list[dest] = newNode; } int main() { int num_vertices = 5; struct Node** adj_list = (struct Node**)malloc(num_vertices * sizeof(struct Node*)); int* visited = (int*)calloc(num_vertices, sizeof(int)); for (int i = 0; i < num_vertices; i++) { adj_list[i] = NULL; } addEdge(adj_list, 0, 1); addEdge(adj_list, 0, 2); addEdge(adj_list, 1, 2); addEdge(adj_list, 2, 0); addEdge(adj_list, 2, 3); addEdge(adj_list, 3, 3); printf("深度优先遍历结果:\n"); DFS(2, adj_list, visited); return 0; } ``` 广度优先遍历广度优先遍历是一种以广度为优先的遍历方法,它从起始顶点开始,访问其所有邻接顶点,然后再访问这些邻接顶点的邻接顶点,依次类推,直到中所有的顶点都被访问过。在C语言中,可以使用队列来实现广度优先遍历邻接表。具体步骤如下: 1. 创建一个数组visited,用于记录每个顶点是否被访问过。 2. 创建一个空队列queue,将起始顶点v入队,并将visited[v]标记为已访问。 3. 从队列中取出一个顶点u,访问u,将其所有邻接顶点入队并标记为已访问。 4. 重复步骤3,直到队列为空。 具体的C语言代码如下: ``` #include <stdlib.h> #include <stdio.h> struct Node { int data; struct Node* next; }; void BFS(int v, struct Node** adj_list, int* visited) { struct Node* queue = (struct Node*)malloc(sizeof(struct Node)); struct Node* front = queue; struct Node* rear = queue; visited[v] = 1; printf("%d ", v); while (front != NULL) { v = front->data; front = front->next; struct Node* temp = adj_list[v]; while (temp != NULL) { int u = temp->data; if (!visited[u]) { visited[u] = 1; printf("%d ", u); struct Node* new_node = (struct Node*)malloc(sizeof(struct Node)); new_node->data = u; new_node->next = NULL; rear->next = new_node; rear = new_node; } temp = temp->next; } } } void addEdge(struct Node** adj_list, int src, int dest) { struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); newNode->data = dest; newNode->next = adj_list[src]; adj_list[src] = newNode; newNode = (struct Node*)malloc(sizeof(struct Node)); newNode->data = src; newNode->next = adj_list[dest]; adj_list[dest] = newNode; } int main() { int num_vertices = 5; struct Node** adj_list = (struct Node**)malloc(num_vertices * sizeof(struct Node*)); int* visited = (int*)calloc(num_vertices, sizeof(int)); for (int i = 0; i < num_vertices; i++) { adj_list[i] = NULL; } addEdge(adj_list, 0, 1); addEdge(adj_list, 0, 2); addEdge(adj_list, 1, 2); addEdge(adj_list, 2, 0); addEdge(adj_list, 2, 3); addEdge(adj_list, 3, 3); printf("广度优先遍历结果:\n"); BFS(2, adj_list, visited); return 0; } ``` 这样,我们就可以使用C语言实现邻接表深度优先遍历广度优先遍历了。 ### 回答3: C语言实现邻接表深度优先遍历广度优先遍历的步骤如下: 深度优先遍历(DFS): 1. 声明一个栈,并将起始顶点压入栈中。 2. 创建一个布尔数组,用来标记每个顶点是否被访问过,并将起始顶点标记为已访问。 3. 循环执行以下步骤,直到栈为空: 1) 弹出栈顶元素,并输出该顶点。 2) 查找该顶点的邻接顶点: a) 若邻接顶点未被访问过,则将其压入栈中,并标记为已访问。 b) 若邻接顶点已被访问过,则继续查找下一个邻接顶点。 4. 遍历结束。 广度优先遍历(BFS): 1. 声明一个队列,并将起始顶点入队。 2. 创建一个布尔数组,用来标记每个顶点是否被访问过,并将起始顶点标记为已访问。 3. 循环执行以下步骤,直到队列为空: 1) 出队一个顶点,并输出该顶点。 2) 查找该顶点的邻接顶点: a) 若邻接顶点未被访问过,则将其入队,并标记为已访问。 b) 若邻接顶点已被访问过,则继续查找下一个邻接顶点。 4. 遍历结束。 在这两种遍历中,我们使用一个布尔数组来记录顶点的访问情况,避免重复访问。同时,栈和队列分别用来记录当前正在访问的顶点,以便按照深度优先或广度优先的顺序进行遍历。 以上是C语言实现邻接表深度优先遍历广度优先遍历的基本步骤,可以通过循环和递归等不同方式来实现具体代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值