图的深度优先遍历算法

1. 实验目的

(1) 掌握图的逻辑结构;

(2) 掌握图的邻接矩阵存储结构;

(3) 验证图的邻接矩阵存储及其深度优先遍历操作的实现。

2. 实验内容

(1) 建立无向图的邻接矩阵存储;

(2) 对建立的无向图,进行深度优先遍历;

3. 实验提示

      定义邻接矩阵存储的无向图结构体MGraph,在其基础上实现题目要求的图建立、深度优先遍历等基本操作。

4. 程序代码

#include <iostream>
using namespace std;
#define MAX_VERTEX 20  
typedef char DataType;
typedef struct
{
	int vertexNum;
	DataType vertexArr[MAX_VERTEX];       //顶点元素数组	 
	int edgeArr[MAX_VERTEX][MAX_VERTEX]; //边矩阵二维数组 
	
}ArrayGraph;

int visited[MAX_VERTEX] = {0};
void ArrayGraph_init(ArrayGraph *pGraph);
void ArrayGraph_create(ArrayGraph *pGraph);
void ArrayGraph_show(ArrayGraph *pGraph);
void DFTraverse(ArrayGraph *pGraph, int i);

int main()
{
	ArrayGraph g;
	ArrayGraph_init(&g);       //初始化图 
	ArrayGraph_create(&g);     //创建图 
	ArrayGraph_show(&g);       //打印图 
	printf("深度优先遍历序列是:");
	DFTraverse(&g, 0);
	system("pause");
	return 0;

}
//初始化为一个无圈图 ,也就是边矩阵中,主对角线元素都是0 
void ArrayGraph_init(ArrayGraph *pGraph)
{
	for (int i = 0; i < MAX_VERTEX; i++)
		pGraph->edgeArr[i][i] = 0;
}
//输入一个图 
void ArrayGraph_create(ArrayGraph *pGraph)
{
	printf("请输入图的顶点个数(不超过20):");
	cin>>pGraph->vertexNum;
	for (int i = 0; i < pGraph->vertexNum; ++i)    //填充顶点数组,也就是输入顶点元素 
	{
		printf("输入第%d个顶点值\n", i + 1);
		scanf_s(" %c", &(pGraph->vertexArr[i]));
	}
	for (int j = 0; j <pGraph->vertexNum; ++j)   //填充边关系 
	{
		for (int i = j + 1; i < pGraph->vertexNum; ++i)
		{
			printf("若元素%c和%c有边,则输入1,否则输入0\t", pGraph->vertexArr[j], pGraph->vertexArr[i]);
			scanf_s("%d", &(pGraph->edgeArr[j][i]));
			pGraph->edgeArr[i][j] = pGraph->edgeArr[j][i];     //对称 
		}
	}
}
void ArrayGraph_show(ArrayGraph *pGraph)
{
	printf("\n\n顶点元素如下\n");
	for (int i = 0; i < pGraph->vertexNum; ++i)
	{
		printf("%-5c", pGraph->vertexArr[i]);
	}
	printf("\n\n");
	puts("边矩阵如下\n\n");
	printf("%-2c", ' ');
	for (int i = 0; i<pGraph->vertexNum; ++i)
		printf("%-5c", pGraph->vertexArr[i]);
	putchar('\n');
	for (int j = 0; j <pGraph->vertexNum; ++j)
	{
		printf("%-2c", pGraph->vertexArr[j]);
		for (int i = 0; i < pGraph->vertexNum; ++i)
		{
			printf("%-5d", pGraph->edgeArr[i][j]);
		}
		putchar('\n');
	}
	printf("\n\n");
}
void DFTraverse(ArrayGraph *pGraph, int i) 
{
	printf("%-5c", pGraph->vertexArr[i]);
	visited[i] = 1;
	for (int j = 0; j < pGraph->vertexNum; j++) {
		if (pGraph->edgeArr[i][j] == 1 && visited[j] == 0)
			DFTraverse(pGraph, j);
	}
}

5. 运行结果

6. 实验心得

        图的创建和深度优先遍历比较好掌握,倒是花了不少时间思考图的打印问题。最终成果还是非常令我满意的。通过一次次修改和尝试,我对图的遍历、创建和打印有了更深的体会。

2. 系统设计 1.用到的抽象数据类型的定义 的抽象数据类型定义: ADT Graph{ 数据对象V:V是具有相同特性的数据元素的集合,称为顶点集 数据关系R: R={VR} VR={<v,w>|v,w∈V且P(v,w),<v,w>表示从v到w的弧, 谓词P(v,w)定义了弧<v,w>的意义或信息} 基本操作P: CreatGraph(&G,V,VR) 初始条件:V是的顶点集,VR是中弧的集合 操作结果:按V和VR的定义构造G DestroyGraph(&G) 初始条件:G存在 操作结果:销毁G InsertVex(&G,v) 初始条件:G存在,v和中顶点有相同特征 操作结果:在G中增添新顶点v …… InsertArc(&G,v,w) 初始条件:G存在,v和w是G中两个顶点 操作结果:在G中增添弧<v,w>,若G是无向的则还增添对称弧<w,v> …… DFSTraverse(G,Visit()) 初始条件:G存在,Visit是顶点的应用函数 操作结果:对进行深度优先遍历,在遍历过程中对每个顶点调用函数Visit一次且仅一次。一旦Visit()失败,则操作失败 BFSTraverse(G,Visit()) 初始条件:G存在,Visit是顶点的应用函数 操作结果:对进行广度优先遍历,在遍历过程中对每个顶点调用函数Visit一次且仅一次。一旦Visit()失败,则操作失败 }ADT Graph 栈的抽象数据类型定义: ADT Stack{ 数据对象:D={ai|ai∈ElemSet,i=1,2,…,n,n≥0} 数据关系:R1={<ai-1,ai>|ai-1,ai∈D,i=2,…,n} 约定an端为栈顶,ai端为栈底 基本操作: InitStack(&S) 操作结果:构造一个空栈S DestroyStack(&S) 初始条件:栈S已存在 操作结果:将S清为空栈 StackEmpty(S) 初始条件:栈S已存在 操作结果:若栈S为空栈,则返回TRUE,否则FALSE …… Push(&S,e) 初始条件:栈S已存在 操作结果:插入元素e为新的栈顶元素 Pop(&S,&e) 初始条件:栈S已存在且非空 操作结果:删除S的栈顶元素,并用e返回其值 StackTraverse(S,visit()) 初始条件:栈S已存在且非空 操作结果:从栈底到栈顶依次对S的每个数据元素调用函数visit(),一旦visit()失败,则操作失效 }ADT Stack 队列的抽象数据类型定义: ADT Queue{ 数据对象:D={ai|ai∈ElemSet,i=1,2,…,n,n≥0} 数据关系:Rl={<ai-1,ai>|ai-1,ai∈D,i=2,…,n} 约定其中ai端为队列头,an端为队列尾。 基本操作: InitQueue(&Q) 操作结果:构造一个空队列Q DestroyQueue(&Q) 初始条件:队列Q已存在 操作结果:队列Q被销毁,不再存在 QueueEmpty(Q) 初始条件:队列Q已存在 操作结果:若Q为空队列,则返回TRUE,否则FALSE …… EnQueue(&Q,e) 初始条件:队列Q已存在 操作结果:插入元素e为Q的新的队尾元素 DeQueue(&Q,&e) 初始条件:Q为非空队列 操作结果:删除Q的队头元素,并用e返回其值 }ADT Queue 2.主程序的流程: 调用CreateDN函数创建的邻接表G; 调用PrintDN函数输出邻接表G; 调用DFSTraverse函数深度优先遍历; 调用BFSTraverse函数广度优先遍历
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值