邻接表实现图的深度遍历和广度遍历

思维导图(房子的主梁架构)

邻接表实现图的深度遍历和广度遍历_第1张图片

(房子的成品外观)

程序测试图1

邻接表实现图的深度遍历和广度遍历_第2张图片

广度遍历图结果

请输入总的顶点的数 :(请输入0 - 100的整数)
6
请输入总的边数 :(请输入0 - 100的整数)
6
请输入第 1 个顶点的名字 :v1
请输入第 2 个顶点的名字 :v2
请输入第 3 个顶点的名字 :v3
请输入第 4 个顶点的名字 :v4
请输入第 5 个顶点的名字 :v5
请输入第 6 个顶点的名字 :v6
请输入一条边所依附的第一个顶点 :
v1
请输入一条边所依附的第二个顶点 :
v2
请输入边的权值(整数) :1
请输入一条边所依附的第一个顶点 :
v1
请输入一条边所依附的第二个顶点 :
v3
请输入边的权值(整数) :2
请输入一条边所依附的第一个顶点 :
v1
请输入一条边所依附的第二个顶点 :
v4
请输入边的权值(整数) :3
请输入一条边所依附的第一个顶点 :
v2
请输入一条边所依附的第二个顶点 :
v5
请输入边的权值(整数) :4
请输入一条边所依附的第一个顶点 :
v3
请输入一条边所依附的第二个顶点 :
v5
请输入边的权值(整数) :5
请输入一条边所依附的第一个顶点 :
v4
请输入一条边所依附的第二个顶点 :
v6
请输入边的权值(整数) :6
请输入开始遍历的顶点:2
广度遍历结果 :
v2 v5 v1 v3 v4 v6

深度遍历图结果

请输入总的顶点的数 :(请输入0 - 100的整数)
6
请输入总的边数 :(请输入0 - 100的整数)
6
请输入第 1 个顶点的名字 :v1
请输入第 2 个顶点的名字 :v2
请输入第 3 个顶点的名字 :v3
请输入第 4 个顶点的名字 :v4
请输入第 5 个顶点的名字 :v5
请输入第 6 个顶点的名字 :v6
请输入一条边所依附的第一个顶点 :
v1
请输入一条边所依附的第二个顶点 :
v2
请输入边的权值(整数) :1
请输入一条边所依附的第一个顶点 :
v1
请输入一条边所依附的第二个顶点 :
v3
请输入边的权值(整数) :2
请输入一条边所依附的第一个顶点 :
v1
请输入一条边所依附的第二个顶点 :
v4
请输入边的权值(整数) :3
请输入一条边所依附的第一个顶点 :
v2
请输入一条边所依附的第二个顶点 :
v5
请输入边的权值(整数) :4
请输入一条边所依附的第一个顶点 :
v3
请输入一条边所依附的第二个顶点 :
v5
请输入边的权值(整数) :5
请输入一条边所依附的第一个顶点 :
v4
请输入一条边所依附的第二个顶点 :
v6
请输入边的权值(整数) :6
请输入开始遍历的顶点:2
深度遍历结果 :
v2 v5 v3 v1 v4 v6

程序测试图2

邻接表实现图的深度遍历和广度遍历_第3张图片

深度遍历图结果

请输入总的顶点的数 :(请输入0 - 100的整数)
8
请输入总的边数 :(请输入0 - 100的整数)
8
请输入第 1 个顶点的名字 :v1
请输入第 2 个顶点的名字 :v2
请输入第 3 个顶点的名字 :v3
请输入第 4 个顶点的名字 :v4
请输入第 5 个顶点的名字 :v5
请输入第 6 个顶点的名字 :v6
请输入第 7 个顶点的名字 :v7
请输入第 8 个顶点的名字 :v8
请输入一条边所依附的第一个顶点 :
v1
请输入一条边所依附的第二个顶点 :
v2
请输入边的权值(整数) :1
请输入一条边所依附的第一个顶点 :
v1
请输入一条边所依附的第二个顶点 :
v3
请输入边的权值(整数) :2
请输入一条边所依附的第一个顶点 :
v2
请输入一条边所依附的第二个顶点 :
v4
请输入边的权值(整数) :3
请输入一条边所依附的第一个顶点 :
v2
请输入一条边所依附的第二个顶点 :
v5
请输入边的权值(整数) :4
请输入一条边所依附的第一个顶点 :
v3
请输入一条边所依附的第二个顶点 :
v6
请输入边的权值(整数) :5
请输入一条边所依附的第一个顶点 :
v3
请输入一条边所依附的第二个顶点 :
v7
请输入边的权值(整数) :6
请输入一条边所依附的第一个顶点 :
v4
请输入一条边所依附的第二个顶点 :
v8
请输入边的权值(整数) :7
请输入一条边所依附的第一个顶点 :
v5
请输入一条边所依附的第二个顶点 :
v8
请输入边的权值(整数) :8
请输入开始遍历的顶点:1
深度遍历结果 :
v1 v3 v7 v6 v2 v5 v8 v4

广度遍历图结果

请输入总的顶点的数 :(请输入0 - 100的整数)
8
请输入总的边数 :(请输入0 - 100的整数)
8
请输入第 1 个顶点的名字 :v1
请输入第 2 个顶点的名字 :v2
请输入第 3 个顶点的名字 :v3
请输入第 4 个顶点的名字 :v4
请输入第 5 个顶点的名字 :v5
请输入第 6 个顶点的名字 :v6
请输入第 7 个顶点的名字 :v7
请输入第 8 个顶点的名字 :v8
请输入一条边所依附的第一个顶点 :
v1
请输入一条边所依附的第二个顶点 :
v2
请输入边的权值(整数) :1
请输入一条边所依附的第一个顶点 :
v1
请输入一条边所依附的第二个顶点 :
v3
请输入边的权值(整数) :2
请输入一条边所依附的第一个顶点 :
v2
请输入一条边所依附的第二个顶点 :
v4
请输入边的权值(整数) :3
请输入一条边所依附的第一个顶点 :
v2
请输入一条边所依附的第二个顶点 :
v5
请输入边的权值(整数) :4
请输入一条边所依附的第一个顶点 :
v4
请输入一条边所依附的第二个顶点 :
v8
请输入边的权值(整数) :5
请输入一条边所依附的第一个顶点 :
v5
请输入一条边所依附的第二个顶点 :
v8
请输入边的权值(整数) :6
请输入一条边所依附的第一个顶点 :
v3
请输入一条边所依附的第二个顶点 :
v6
请输入边的权值(整数) :7
请输入一条边所依附的第一个顶点 :
v3
请输入一条边所依附的第二个顶点 :
v7
请输入边的权值(整数) :8
请输入开始遍历的顶点:1
广度遍历结果 :
v1 v3 v2 v7 v6 v5 v4 v8

(房子的砖头部分)

"ALG.h"头文件

定义图及其各种操作

#pragma once
#include 
#include 
using namespace std;
const int  MVNum = 100;

//边结点定义
typedef struct ArcNode {
	int adjvex;					//该边所指向的顶点在表头结点表数组的下标
	struct  ArcNode* nextarc;	//该边指向下一条边的指针
	int info;					 //边的权值
}ArcNode;

//顶点和顶点表的定义
typedef struct VNode {
	string data;				 //顶点的名称
	ArcNode* firstarc;			//指向第一条依附在该顶点的第一条边
} VNode, AdjList[MVNum];			//定义一个表头结点表的数组类型

								//邻接表的定义
typedef struct {
	AdjList vertices;			//表头结点表
	int vexnum, arcnum;			//图的顶点数和边数
}ALgraph;

//获取输入结点在表头结点表的数组下标
int LocateVex(ALgraph G, VNode* p) {
 	for (int i = 0; i <= G.vexnum; i++) {
		if (G.vertices[i].data == p->data)
			return i;
	}
	return -1;
}
//构造邻接表表示无向图
/*  需求:
	1,表头结点存储图的各个顶点的名字,相应边链表的头结点的指针域
	分析:
	1,接收键盘录入的总顶点数,总边数
	2,for循环,逐个录入图的每一个结点信息(名,指针域初始化未NULL),构造表头结点表
	3,for循环,输入 图的各边信息(边的依附顶点),通过依附顶点在表头结点的值获取顶点在表头结点的数组的下标值,
	根据获取的下标,生成新的边界点,为结点的各个属性赋值,用链表前插法链入顶点的边链表中
*/
void CreateUDG(ALgraph &G) {
	//1,接收键盘录入的总顶点数,总边数
	//while (true) {
	cout << "请输入总的顶点的数 :(请输入0 - 100的整数)" << endl;
	cin >> G.vexnum;
	cout << "请输入总的边数 :(请输入0 - 100的整数)" << endl;
	cin >> G.arcnum;
	//if ((G.vexnum >= 0 && G.vexnum < 100) && (G.arcnum >= 0 && G.arcnum <= 100)) {
	//	cout << "录入成功!\n";
	//	break;
//	}
	//else {
	//	cout << "你的输入有误,请从新输入。" << endl;
	//}
//}
	cout << G.vexnum << G.arcnum;

	//2,for循环,逐个录入图的每一个结点信息(名,指针域初始化未NULL),构造表头结点表
	for (int i = 0; i < G.vexnum; i++) {
		cout << "请输入第 " << i + 1 << " 个顶点的名字 :";
		cin >> G.vertices[i].data;
		G.vertices[i].firstarc = NULL;
	}
	//3,for循环,输入 图的各边信息(边的依附顶点),通过依附顶点在表头结点的值获取顶点在表头结点的数组的下标值,
	//	根据获取的下标,生成新的边界点,为结点的各个属性赋值,用链表前插法链入顶点的边链表中,构造邻接边表
	VNode* v1 = new VNode;
	VNode* v2 = new VNode;
	for (int k = 0; k < G.arcnum; k++) {
		cout << "请输入一条边所依附的第一个顶点 :" << endl;
		cin >> v1->data;
		cout << "请输入一条边所依附的第二个顶点 :" << endl;
		cin >> v2->data;
		int i = LocateVex(G, v1);
		int j = LocateVex(G, v2);
		//头插法为Vi插入新的边结点
		ArcNode * p1 = new ArcNode;
		cout << "请输入边的权值(整数) :";
		cin >> p1->info;
		p1->adjvex = j; //邻接结点在头结点表的下标
		p1->nextarc = G.vertices[i].firstarc;
		G.vertices[i].firstarc = p1;
		//头插法为Vj插入新的边结点
		ArcNode * p2 = new ArcNode;
		p2->info = p1->info;
		p2->adjvex = i;
		p2->nextarc = G.vertices[j].firstarc;
		G.vertices[j].firstarc = p2;
	}
}
void Opertion_Create()
{
	ALgraph G;
	CreateUDG(G);
}
//定义辅助数组
bool visited[MVNum];

"DFS.h"头文件

实现深度遍历算法

#pragma once
#include"ALG.h"



//深度遍历核心函数
void DFS(ALgraph G, int v) { //从第V个顶点开始遍历
	//1,访问第V个顶点
	cout << G.vertices[v].data << " ";
	visited[v] = true; //置访问标志数组相应的分量值为true
	ArcNode * p = G.vertices[v].firstarc; //获取被访问顶点的边链表的首元结点的指针
	while (p) {
		int w = p->adjvex; //获取v顶点的邻接顶点
		if (visited[w]== false) //判断该顶点是否被访问过
			DFS(G, w);
		p = p->nextarc; //指向下一个边结点
	}
}
//深度遍历测试函数
void DFS_Traverse(ALgraph G) {
	//访问标志辅助数组初始化
 	for (int i = 0; i < MVNum; i++)
	{
		visited[i] = false;
	}
	//连通图遍历
	int v;
	cout << "请输入开始遍历的顶点:";
	cin >> v;
	DFS(G, v-1);
	//非连通图遍历
	/*
	for (int v = 0; v < G.vexnum; v++) {
		if (visited[v] == false)
			DFS(G, v);
	}
	*/
}
void Opreation_DFS() {
	//2,创建图的邻接表
	ALgraph G;
	CreateUDG(G);
	//3,对图进行深度遍历
	DFS_Traverse(G);
}

"BFS.h"头文件

#pragma once
#include"ALG.h"

//队列结点的结构
typedef struct Qnode {
	int data;
	struct Qnode * next;
}Qnode, *QueuePtr;

//链表队列结构
typedef struct {
	QueuePtr front; //队头指针
	QueuePtr rear;	//队尾指针
}LinkQueue;

//初始化队列
void InitQueue(LinkQueue &Q) {
	Q.front = Q.rear = new Qnode;	//生成新的结点作为头结点,初始化队头队尾指针
	Q.front->next = NULL;	//头结点的指针域为空
}

//链队入队
bool EnQueue(LinkQueue &Q, int e) {
	Qnode * p = new Qnode; //创建一个新的结点
	p->data = e;
	p->next = Q.front->next;
	Q.rear->next = p; //插入新节点到队尾
	Q.rear = p; //修改队尾指针
	return true;
}

//链队出队
bool DeQueue(LinkQueue &Q, int &e) {
	if (Q.front == Q.rear)
		return false;
	Qnode * p; //保存头结点指针,用于释放空间
	p = Q.front->next; //指向队头结点
	e = p->data; //获取队头结点的元素的值
	Q.front->next = p->next; //修改头指针
	if (Q.rear == p)  //判断删除的元素是否为最后一个元素,避免空指针异常,将队尾指针重新指向队头指针
		Q.rear = Q.front;
	Q.rear->next = Q.front->next; //最后一个结点指向首元结点
	delete p;
	return true;
}

//销毁队列
void DeleteQueue(LinkQueue &Q) {
	while (Q.front)
	{
		Q.rear = Q.front->next;
		delete Q.front;
		Q.front = Q.rear;
	}
}

//ALG.h头文件声明辅助数组

//广度遍历核心函数
void BFS(ALgraph G, int v) {
	LinkQueue Q;
	InitQueue(Q);
	cout << G.vertices[v].data << " ";
	visited[v] = true;
	EnQueue(Q,v);
	while (Q.front != Q.rear) {
		int u;
		DeQueue(Q, u);
		ArcNode * p = G.vertices[u].firstarc; //获取被访问顶点的边链表的首元结点的指针
		while (p) { // 先输入一个顶点的所有临界点
			int w = p->adjvex; //获取v顶点的邻接顶点
			if (visited[w] == false) {//判断该顶点是否被访问过
				cout << G.vertices[w].data << " ";  
				visited[w] = true;  //修改辅助表
				EnQueue(Q, w); //已经输出的邻接点入队
			}
			p = p->nextarc; //指向顶点的下一个邻接点
		}
		
	}
	
	
}

//广度遍历操作函数
void BFS_Traverse(ALgraph G) {
	//访问标志辅助数组初始化
	for (int i = 0; i < MVNum; i++)
	{
		visited[i] = false;
	}
	//连通图遍历
	int v;
	cout << "请输入开始遍历的顶点:";
	cin >> v;
	BFS(G, v - 1);
}
void Opreation_BFS() {
	//2,创建图的邻接表
	ALgraph G;
	CreateUDG(G);
	//3,对图进行深度遍历
	BFS_Traverse(G);
}

photos.cpp 主函数

用于测试和实现头文件中的各种算法操作函数

// photos.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。


#include "pch.h"
#include"ALG.h"
#include"DFS.h"
#include"BFS.h"
int main()
{
	//Opertion_Create();
	//Opreation_DFS();
	Opreation_BFS();
}


你可能感兴趣的:(数据结构)