C++构造无向图,邻接表,深度优先遍历,广度优先遍历

目录

定义无向图邻接表

构造无向图

打印邻接表

无向图邻接表深度优先遍历(DFS)

无向图邻接表广度优先遍历(BFS)

测试

 完整代码


定义无向图邻接表

#define MVnum 100 //最大定点数

//边(弧)的结点结构定义
struct ArcNode
{
	int adjvex; //该边所指向的顶点的位置
	ArcNode* nextarc; //指向下一条边的指针
};

//顶点的结点结构定义
struct VexNode
{
	string data; //顶点信息
	ArcNode* fristarc; //指向第一条依附该顶点的边的指针
};

//图的结构定义
struct ALGraph
{
	VexNode vertices[MVnum]; //邻接表数组
	int vexnum, arcnum; //图的当前总顶点数和总边数
};

构造无向图

             (1)输入总顶点数和总边数。
             (2)建立顶点表
                        依次输入点的信息存入顶点表中
                        使每个表头结点的指针域初始化为NULL
             (3)创建邻接表
                         依次输入每条边依附的两个顶点
                         确定两个顶点的序号i和j,建立边结点
                         将此边结点分别插入到vi和vj,对应的两个边链表的头部

//声明
int LocateVex(ALGraph G, string u);

//采用邻接表构建无向图
bool CreateUDG(ALGraph& G)
{
	//1.输入总顶点数和总边数
	cout << "请输入顶点数:" << endl;
	cin >> G.vexnum;
	cout << "请输入边数:" << endl;
	cin >> G.arcnum;

	//2.建立顶点表
	cout << "请输入顶点信息:" << endl;
	for (int i = 0; i < G.vexnum; i++)
	{
		cin >> G.vertices[i].data; //输入顶点值
		G.vertices[i].fristarc = NULL; //初始化表头结点的指针域
	}

	//3.创建邻接表
	cout << "请输入一条边所依附的两个顶点:" << endl;
	for (int k = 0; k < G.arcnum; k++)
	{
		string v1, v2;
		cin >> v1 >> v2; //输入一条边所依附的两个顶点
		int i = LocateVex(G, v1);
		int j = LocateVex(G, v2);

		ArcNode* p1 = new ArcNode; //生成新的边结点
		p1->adjvex = j; //邻接点序号为j
		p1->nextarc = G.vertices[i].fristarc;
		G.vertices[i].fristarc = p1; //将新结点p1插入顶点vi的边表头部

		ArcNode* p2 = new ArcNode; //生成另一个对称的新的边结点
		p2->adjvex = i; //邻接点序号为i
		p2->nextarc = G.vertices[j].fristarc;
		G.vertices[j].fristarc = p2; //将新结点p2插入顶点vj的边表头部
	}
	return true;
}

//在图G中查找顶点u,存在返回顶点表中的下标,否则返回-1
int LocateVex(ALGraph G, string u)
{
	for (int i = 0; i < G.vexnum; i++)
	{
		if (G.vertices[i].data == u)
		{
			return i;
		}
	}
	return -1;
}

打印邻接表

//打印
void PrintVex(ALGraph G)
{
	for (int i = 0; i < G.vexnum; i++)
	{
		cout << G.vertices[i].data << ": ";
		while (G.vertices[i].fristarc)
		{
			cout << G.vertices[i].fristarc->adjvex<<" ";
			G.vertices[i].fristarc = G.vertices[i].fristarc->nextarc;
		}
		cout << endl;
	}
}

无向图邻接表深度优先遍历(DFS)

1、在访问图中某一起始顶点v后,由v出发,访问它的任一邻接顶点w1;

2、再从w1出发,访问与w1邻接但还未被访问过的顶点w2;

3、然后再从w2出发,进行类似的访问,...

4、如此进行下去,直至到达所有的邻接顶点都被访问过的顶点u为止。接着,退回一步,退到前一次刚访问过的顶点,看是否还有其它没有被访问的邻接顶点。

5、如果有,则访问此顶点,之后再从此顶点出发,进行与前述类似的访问;

6、如果没有,就再退回一步进行搜索。重复上述过程,直到连通图中所有顶点都被访问过为止。

bool visited[MVnum]; //深度优先访问标志数组,初始为false;

//无向图邻接表深度优先遍历
void DFS(ALGraph G, int v)
{
	//访问第v个顶点,并置访问标志数组为true
	cout << G.vertices[v].data << " ";
	visited[v] = true;
	ArcNode *p = G.vertices[v].fristarc; //p指向v的边链表的第一个边结点
	while (p)//边结点非空
	{
		int w = p->adjvex;//表示w是v的邻接点
		if (!visited[w]) //如果w为访问,则递归调用DFS
		{
			DFS(G, w);
		}
		p = p->nextarc; //p指向下一边结点
	}
}

无向图邻接表广度优先遍历(BFS)

1、从图的一结点出发,首先依次访问该结点的所有邻接结点v1,v2......vn再按这些顶点被访问的先后次序依次访问与它们相邻的所有未被访问的顶点。

2、重复此过程,直至所有顶点均被访问为止。

bool visited1[MVnum]; //广度优先访问标志数组,初始为false;

//无向图邻接表广度优先遍历
void BFS(ALGraph G, int v)
{
	//访问第v个顶点,并置访问标志数组为true
	cout << G.vertices[v].data << " ";
	visited1[v] = true;
	queue<int>Q; //创建队列Q
	Q.push(v); //v进队
	while (!Q.empty()) //队列非空
	{
		int p = Q.front(); //将队头元素赋给p
		Q.pop(); //删除队顶元素
		ArcNode* arc = G.vertices[p].fristarc; //arc指向p的边链表的第一个边结点
		while (arc) //边结点非空
		{
			if (!visited1[arc->adjvex]) //判断边结点arc中指向顶点的位置是否被访问
			{
				cout << G.vertices[arc->adjvex].data << " ";//输出边结点arc记录位置的顶点值
				visited1[arc->adjvex] = true; //标记为true
				Q.push(arc->adjvex); //边结点arc指向顶点中的位置入队
			}
			arc = arc->nextarc; //arc指向下一边结点
		}
		
	}
}

测试

int main()
{
	ALGraph G;
	CreateUDG(G); //构造无向图邻接表
	cout << "图G的邻接表为:" << endl;
	PrintVex(G); //打印邻接表
	int v = 0;
	cout << "深度优先遍历为:" << endl;
	DFS(G, v);
	cout << endl;
	cout << "广度优先遍历为:" << endl;
	BFS(G, v);
	cout << endl;

	system("pause");
	return 0;
}

 

 完整代码

#include<iostream>
using namespace std;
#include<queue>

#define MVnum 100 //最大定点数

//边(弧)的结点结构定义
struct ArcNode
{
	int adjvex; //该边所指向的顶点的位置
	ArcNode* nextarc; //指向下一条边的指针
};

//顶点的结点结构定义
struct VexNode
{
	string data; //顶点信息
	ArcNode* fristarc; //指向第一条依附该顶点的边的指针
};

//图的结构定义
struct ALGraph
{
	VexNode vertices[MVnum]; //邻接表数组
	int vexnum, arcnum; //图的当前总顶点数和总边数
};

bool visited[MVnum]; //深度优先访问标志数组,初始为false;

bool visited1[MVnum]; //广度优先访问标志数组,初始为false;

//声明
int LocateVex(ALGraph G, string u);

//采用邻接表构建无向图
bool CreateUDG(ALGraph& G)
{
	//1.输入总顶点数和总边数
	cout << "请输入顶点数:" << endl;
	cin >> G.vexnum;
	cout << "请输入边数:" << endl;
	cin >> G.arcnum;

	//2.建立顶点表
	cout << "请输入顶点信息:" << endl;
	for (int i = 0; i < G.vexnum; i++)
	{
		cin >> G.vertices[i].data; //输入顶点值
		G.vertices[i].fristarc = NULL; //初始化表头结点的指针域
	}

	//3.创建邻接表
	cout << "请输入一条边所依附的两个顶点:" << endl;
	for (int k = 0; k < G.arcnum; k++)
	{
		string v1, v2;
		cin >> v1 >> v2; //输入一条边所依附的两个顶点
		int i = LocateVex(G, v1);
		int j = LocateVex(G, v2);

		ArcNode* p1 = new ArcNode; //生成新的边结点
		p1->adjvex = j; //邻接点序号为j
		p1->nextarc = G.vertices[i].fristarc;
		G.vertices[i].fristarc = p1; //将新结点p1插入顶点vi的边表头部

		ArcNode* p2 = new ArcNode; //生成另一个对称的新的边结点
		p2->adjvex = i; //邻接点序号为i
		p2->nextarc = G.vertices[j].fristarc;
		G.vertices[j].fristarc = p2; //将新结点p2插入顶点vj的边表头部
	}
	return true;
}

//在图G中查找顶点u,存在返回顶点表中的下标,否则返回-1
int LocateVex(ALGraph G, string u)
{
	for (int i = 0; i < G.vexnum; i++)
	{
		if (G.vertices[i].data == u)
		{
			return i;
		}
	}
	return -1;
}

//打印
void PrintVex(ALGraph G)
{
	for (int i = 0; i < G.vexnum; i++)
	{
		cout << G.vertices[i].data << ": ";
		while (G.vertices[i].fristarc)
		{
			cout << G.vertices[i].fristarc->adjvex<<" ";
			G.vertices[i].fristarc = G.vertices[i].fristarc->nextarc;
		}
		cout << endl;
	}
}

//无向图邻接表深度优先遍历
void DFS(ALGraph G, int v)
{
	//访问第v个顶点,并置访问标志数组为true
	cout << G.vertices[v].data << " ";
	visited[v] = true;
	ArcNode *p = G.vertices[v].fristarc; //p指向v的边链表的第一个边结点
	while (p)//边结点非空
	{
		int w = p->adjvex;//表示w是v的邻接点
		if (!visited[w]) //如果w为访问,则递归调用DFS
		{
			DFS(G, w);
		}
		p = p->nextarc; //p指向下一边结点
	}
}

//无向图邻接表广度优先遍历
void BFS(ALGraph G, int v)
{
	//访问第v个顶点,并置访问标志数组为true
	cout << G.vertices[v].data << " ";
	visited1[v] = true;
	queue<int>Q; //创建队列Q
	Q.push(v); //v进队
	while (!Q.empty()) //队列非空
	{
		int p = Q.front(); //将队头元素赋给p
		Q.pop(); //删除队顶元素
		ArcNode* arc = G.vertices[p].fristarc; //arc指向p的边链表的第一个边结点
		while (arc) //边结点非空
		{
			if (!visited1[arc->adjvex]) //判断边结点arc中指向顶点的位置是否被访问
			{
				cout << G.vertices[arc->adjvex].data << " ";//输出边结点arc记录位置的顶点值
				visited1[arc->adjvex] = true; //标记为true
				Q.push(arc->adjvex); //边结点arc指向顶点中的位置入队
			}
			arc = arc->nextarc; //arc指向下一边结点
		}
		
	}
}

int main()
{
	ALGraph G;
	CreateUDG(G); //构造无向图邻接表
	cout << "图G的邻接表为:" << endl;
	PrintVex(G); //打印邻接表
	int v = 0;
	cout << "深度优先遍历为:" << endl;
	DFS(G, v);
	cout << endl;
	cout << "广度优先遍历为:" << endl;
	BFS(G, v);
	cout << endl;

	system("pause");
	return 0;
}

  • 7
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是基于邻接表无向图广度优先遍历的C代码: ```c #include <stdio.h> #include <stdlib.h> #define MAXV 1000 // 顶点数的最大值 typedef struct node *node_pointer; struct node{ int vertex; // 邻接点在顶点表中的下标 node_pointer next; // 下一个邻接点 }; typedef struct graph *graph_pointer; struct graph{ node_pointer adj_list[MAXV]; int nvertices; // 中顶点数 }; int visited[MAXV]; void bfs(graph_pointer G, int start){ int queue[MAXV], front = -1, rear = -1; node_pointer ptr; int v; queue[++rear] = start; visited[start] = 1; while(front != rear){ v = queue[++front]; printf("%d ", v); // 访问顶点v // 将顶点v的邻接点加入队列中 for (ptr = G->adj_list[v]; ptr != NULL; ptr = ptr->next){ if(!visited[ptr->vertex]){ queue[++rear] = ptr->vertex; visited[ptr->vertex] = 1; } } } } int main(){ graph_pointer G; int i, j, n, m, v1, v2; printf("输入顶点数和边数:"); scanf("%d%d", &n, &m); G = (graph_pointer)malloc(sizeof(struct graph)); G->nvertices = n; // 初始化邻接表 for (i = 1; i <= n; i++){ G->adj_list[i] = NULL; } // 建立邻接表 for (i = 1; i <= m; i++){ printf("输入一条边的两个顶点:"); scanf("%d%d", &v1, &v2); node_pointer new_node1 = (node_pointer)malloc(sizeof(struct node)); node_pointer new_node2 = (node_pointer)malloc(sizeof(struct node)); new_node1->vertex = v2; new_node1->next = G->adj_list[v1]; G->adj_list[v1] = new_node1; new_node2->vertex = v1; new_node2->next = G->adj_list[v2]; G->adj_list[v2] = new_node2; } // 广度优先遍历 printf("广度优先遍历的结果:"); for (i = 1; i <= n; i++){ visited[i] = 0; } bfs(G, 1); return 0; } ``` 代码中,我们定义了一个结构体 `graph` 来存储邻接表,其中 `adj_list` 数组存储每个顶点的邻接点链表,`nvertices` 存储中的顶点数。`node` 结构体用于定义邻接点,其中 `vertex` 存储邻接点在顶点表中的下标,`next` 存储下一个邻接点的指针。我们还定义了一个 `visited` 数组,用于标记每个顶点是否已经遍历过。 在 `main()` 函数中,我们首先从用户输入中读入的顶点数和边数,然后利用 `malloc()` 动态分配 `graph` 结构体的存储空间。接着,我们初始化邻接表,将每个顶点的邻接点指针初始化为 `NULL`。然后,我们读入每一条边,并且根据边的两个顶点建立邻接表。最后,我们调用 `bfs()` 函数进行广度优先遍历,从顶点 `1` 开始遍历整个。 `bfs()` 函数中,我们使用 `queue` 数组来存储待遍历的顶点,`front` 和 `rear` 分别指向队列的头和尾。我们首先将起始顶点 `start` 加入队列中,并标记为已访问。然后,我们不断从队列中取出一个顶点 `v`,访问该顶点,并将其邻接点加入队列中(如果邻接点尚未访问过)。这一过程一直持续到队列为空。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值