图的深度优先遍历算法

      图的深度优先遍历类似于树的先根遍历,首先访问顶点v0,再访问v0的邻接点v1,同样递归访问v1的邻接点,若到vi时的所有邻接点均以访问完毕,则退回上一个顶点查看是否有邻接点为被访问,若有临界点w未被访问,则访问递归w,否则继续退回前一个结点。全部结点访问完毕时,算法结束。

      给出邻接表表示的图的递归和非递归算法,下面是图的邻接矩阵和邻接表表示,设置Visited[i]来记录结点i是否被访问。

#include <stdio.h>
#include <malloc.h>
#define MAXV 50

int visited[MAXV];

typedef int InfoType;

typedef struct 
{
	int no;
	InfoType info;
}VertType;

typedef struct
{
	int edges[MAXV][MAXV];
	VertType vexs[MAXV];
	int n,e;
}MGraph;

typedef struct ANode
{
	int adjvex;
	InfoType info;
	struct ANode *nextarc;
}ArcNode;

typedef int Vertex;

typedef struct
{
	Vertex data;
	ArcNode *firstarc;
}VNode;

typedef VNode AdjList[MAXV];

typedef struct
{
	AdjList adjlist;
	int n,e;
}ALGraph;
        递归算法如下:

void DFS(ALGraph *G,int v)
{
	ArcNode *p;
	int n=G->n;
	visited[v] = 1;
	printf("%3d",v);
	p = G->adjlist[v].firstarc;
	while(p)
	{
		if(visited[p->adjvex] == 0)
			DFS(G,p->adjvex);
		p = p->nextarc;
	}
}
        非递归算法如下:

void DFS1(ALGraph *G, int v)
{
	ArcNode *p;
	ArcNode *St[MAXV];
	int top=-1;
	int i,w,n=G->n;
	for(i=0; i<n; i++)
		visited[i] = 0;
	visited[v] = 1;
	printf("%3d",v);
	top++;
	St[top] = G->adjlist[v].firstarc;
	while(top>=0)
	{
		p = St[top];
		top--;
		while(p!=NULL)
		{
			w = p->adjvex;
			if(visited[w] == 0)
			{
				visited[w] = 1;
				printf("%3d",w);
				top++;
				St[top] = G->adjlist[w].firstarc;
				break;		
			}
			p = p->nextarc;
		}
	}
}
void main()
{
	MGraph g;
	ALGraph *G;
	int i,j;
	int A[MAXV][6] = {
		{0,5,0,7,0,0},
		{0,0,4,0,0,0},
		{8,0,0,0,0,9},
		{0,0,5,0,0,6},
		{0,0,0,5,0,0},
		{3,0,0,0,1,0}
	};
	g.n = 6;
	g.e =10;
	for(i=0; i<g.n; i++)
		for(j=0; j<g.n; j++)
			g.edges[i][j] = A[i][j];
	for(i=0; i<g.n; i++)
		visited[i] = 0;
	MatToList(g,G);				
	printf("图G的邻接表:\n");
	DispList(G);
	printf("从顶点0开始的DFS(递归算法):\n");
	DFS(G,0);
	printf("\n");
	printf("从顶点0开始的DFS(非递归算法):\n");
	DFS1(G,0);
	printf("\n");
}
      运行结果:



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、付费专栏及课程。

余额充值