数据结构(C实现)------- 图的深度优先遍历

[本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020]

算法描述:

假设给定图G的初始状态是所有顶点均未曾访问过,在G中任选一顶点vi为初始的出发点,则深度优先遍历可定义如下: 首先访问出发点vi,并将其标记为已被访问过;然后,依次从vi出发遍历vi的每一个邻接点vj,若vj未曾访问过,则以vj为新的出发点继续进行深度优先遍历,直至图中所有和vi有路径相通的顶点都被访问到为止。因此,若G是连通图,则从初始出发点开始的遍历过程结束也就意味着完成了对图G的遍历。

算法实现:

分别以邻接矩阵和邻接表作为图的存储结构,给出连通图的深度优先搜索遍历的递归算法。算法描述如下:

(1) 访问出发点vi,并将其标记为已被访问已访问过。

(2) 遍历vi的每一个邻接点vj,若vj未曾访问过,则以vj为新的出发点继续进行深度优先遍历。

完整代码:

用邻接矩阵实现深度优先搜索算法源代码如下:

/**
 * 深度遍历图
 **/
void DFS_MG(MGraph MG,int i){
	visit[i] = 1;
	printf("%c\t",MG.vexs[i]);
	int j;
	for (j = 1; j <= MG.vexnum;j++){
		if(visit[j] == 0 && MG.arcs[i][j] == 1)
			DFS_MG(MG,j);
	}
}

用邻接表实现深度优先搜索算法源代码如下:

/**
 * 深度遍历图
 **/
void DFS_AG(ALGraph AG,int i){
	ArcPtr p;
	printf("%c\t",AG.vertices[i].vexdata);
	visit[i] = 1;
	p = AG.vertices[i].firstarc;
	while( p!= NULL ){
		if(visit[p->adjvex] == 0)
			DFS_AG(AG,p->adjvex);
		p = p->nextarc;
	}
}

算法说明:

对于具有n个顶点,e条边的连通图,算法DFS_MG,DFS_AG
均调用n次。除了初始调用是来自外部,基于n-1次调用均是来自DFS_MG和DFS_AG内部的递归调用,用邻接矩阵实现时,遍历一个顶点的所有邻接点需要O(n)时间,则遍历整个图需要O(n^2),即DFS_MG的时间复杂度为O(n^2)。

用邻接表实现时,遍历n个顶点的所有邻接点是对边表节点的扫描一遍,故算法DFS_AG时间复杂度为O(n+e)。

采用深度优先遍历算法时,都要用到访问标志,所以该算法的空间复杂度为O(n).

邻接矩阵实现深度优先搜索算法完整代码如下:

/*
 ============================================================================
 Name        : Graph.c
 Author      : jesson20121020
 Version     : 1.0
 Description : create Graph using Adjacency Matrix, Ansi-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#define MAX_VEX_NUM 50
typedef char VertexType;
typedef enum {
	DG, UDG
} GraphType;
typedef struct {
	VertexType vexs[MAX_VEX_NUM];
	int arcs[MAX_VEX_NUM][MAX_VEX_NUM];
	int vexnum, arcnum;
	GraphType type;
} MGraph;

//设置图中顶点访问标志
int visit[MAX_VEX_NUM];

/**
 * 根据名称得到指定顶点在顶点集合中的下标
 * vex  顶点
 * return 如果找到,则返回下标,否则,返回0
 */
int getIndexOfVexs(char vex, MGraph *MG) {
	int i;
	for (i = 1; i <= MG->vexnum; i++) {
		if (MG->vexs[i] == vex) {
			return i;
		}
	}
	return 0;
}

/**
 * 创建邻接矩阵
 */
void create_MG(MGraph *MG) {
	int i, j, k;
	int v1, v2, type;
	char c1, c2;
	printf("Please input graph type DG(0) or UDG(1) :");
	scanf("%d", &type);
	if (type == 0)
		MG->type = DG;
	else if (type == 1)
		MG->type = UDG;
	else {
		printf("Please input correct graph type DG(0) or UDG(1)!");
		return;
	}

	printf("Please input vexmun : ");
	scanf("%d", &MG->vexnum);
	printf("Please input arcnum : ");
	scanf("%d", &MG->arcnum);
	getchar();
	for (i = 1; i <= MG->vexnum; i++) {
		printf("Please input %dth vex(char):", i);
		scanf("%c", &MG->vexs[i]);
		getchar();
	}

	//初始化邻接矩阵
	for (i = 1; i <= MG->vexnum; i++) {
		for (j = 1; j <= MG->vexnum; j++) {
			MG->arcs[i][j] = 0;
		}
	}

	//输入边的信息,建立邻接矩阵
	for (k = 1; k <= MG->arcnum; k++) {
		printf("Please input %dth arc v1(char) v2(char) : ", k);

		scanf("%c %c", &c1, &c2);
		v1 = getIndexOfVexs(c1, MG);
		v2 = getIndexOfVexs(c2, MG);
		if (MG->type == 1)
			MG->arcs[v1][v2] = MG->arcs[v2][v1] = 1;
		else
			MG->arcs[v1][v2] = 1;
		getchar();
	}
}
/**
 * 打印邻接矩阵和顶点信息
 */
void print_MG(MGraph MG) {
	int i, j;
	if(MG.type == DG){
		printf("Graph type: Direct graph\n");
	}
	else{
		printf("Graph type: Undirect graph\n");
	}

	printf("Graph vertex number: %d\n",MG.vexnum);
	printf("Graph arc number: %d\n",MG.arcnum);

	printf("Vertex set:\n ");
	for (i = 1; i <= MG.vexnum; i++)
		printf("%c\t", MG.vexs[i]);
	printf("\nAdjacency Matrix:\n");

	for (i = 1; i <= MG.vexnum; i++) {
		j = 1;
		for (; j < MG.vexnum; j++) {
			printf("%d\t", MG.arcs[i][j]);
		}
		printf("%d\n", MG.arcs[i][j]);
	}
}

/**
 * 初始化顶点访问标志
 **/
void init_Visit(){
	int i;
	for(i = 0;i < MAX_VEX_NUM;i++)
		visit[i] = 0;
}

/**
 * 深度遍历图
 **/
void DFS_MG(MGraph MG,int i){
	visit[i] = 1;
	printf("%c\t",MG.vexs[i]);
	int j;
	for (j = 1; j <= MG.vexnum;j++){
		if(visit[j] == 0 && MG.arcs[i][j] == 1)
			DFS_MG(MG,j);
	}
}

/**
 * 主函数
 */
int main(void) {
	MGraph MG;
	create_MG(&MG);
	print_MG(MG);
	printf("The result of DFS:\n");
	DFS_MG(MG,1);

	return EXIT_SUCCESS;
}

邻接表实现深度优先搜索算法的完整代码如下:

/*
 ============================================================================
 Name        : ALGraph.c
 Author      : jesson20121020
 Version     : 1.0
 Copyright   : Your copyright notice
 Description : Graph using linkList, Ansi-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>

#include <stdio.h>

#define MAX_VERTEX_NUM 50
typedef enum {
	DG, UDG
} GraphType;
typedef char VertexType;
//表节点
typedef struct ArcNode {
	int adjvex; //邻接节点
	int weight; //边权重
	struct ArcNode *nextarc; //下一个节点指针
} ArcNode, *ArcPtr;
//头节点
typedef struct {
	VertexType vexdata;
	int id;
	ArcPtr firstarc;
} VNode;
//头节点数组
typedef struct {
	VNode vertices[MAX_VERTEX_NUM];
	int vexnum, arcnum;
	GraphType type;
} ALGraph;

int visit[MAX_VERTEX_NUM];

/**
 * 根据顶点字符得到在顶点数组中的下标
 */
int getIndexOfVexs(char vex, ALGraph *AG) {
	int i;
	for (i = 1; i <= AG->vexnum; i++) {
		if (AG->vertices[i].vexdata == vex) {
			return i;
		}
	}
	return 0;
}
/**
 * 创建邻接表
 */
void create_AG(ALGraph *AG) {
	ArcPtr p,q;
	int i, j, k, type;
	VertexType v1, v2;
	printf("Please input graph type UG(0) or UDG(1) :");
	scanf("%d", &type);
	if (type == 0)
		AG->type = DG;
	else if (type == 1)
		AG->type = UDG;
	else {
		printf("Please input correct graph type UG(0) or UDG(1)!");
		return;
	}

	printf("please input vexnum:");
	scanf("%d", &AG->vexnum);
	printf("please input arcnum:");
	scanf("%d", &AG->arcnum);
	getchar();
	for (i = 1; i <= AG->vexnum; i++) {
		printf("please input the %dth vex(char) : ", i);
		scanf("%c", &AG->vertices[i].vexdata);
		getchar();
		AG->vertices[i].firstarc = NULL;
	}

	for (k = 1; k <= AG->arcnum; k++) {
		printf("please input the %dth arc v1(char) v2(char) :", k);
		scanf("%c %c", &v1, &v2);
		i = getIndexOfVexs(v1, AG);
		j = getIndexOfVexs(v2, AG);

		//根据图的类型创建邻接表
		//方法1,插入到链表头
		/*
		if (AG->type == DG) { //有向图
			p = (ArcPtr) malloc(sizeof(ArcNode));
			p->adjvex = j;
			p->nextarc = AG->vertices[i].firstarc;
			AG->vertices[i].firstarc = p;
		} else { //无向图
			p = (ArcPtr) malloc(sizeof(ArcNode));
			p->adjvex = j;
			p->nextarc = AG->vertices[i].firstarc;
			AG->vertices[i].firstarc = p;

			p = (ArcPtr) malloc(sizeof(ArcNode));
			p->adjvex = i;
			p->nextarc = AG->vertices[j].firstarc;
			AG->vertices[j].firstarc = p;
		}
		*/
		//方法2,插入到链表尾
		if (AG->type == DG) { //有向图
			p = (ArcPtr) malloc(sizeof(ArcNode));
			p->adjvex = j;
			//表为空
			if(AG->vertices[i].firstarc == NULL){
				AG->vertices[i].firstarc = p;
			}
			else{
				//找最后一个表节点
				q = AG->vertices[i].firstarc;
				while(q->nextarc != NULL){
					q = q->nextarc;
				}
				q->nextarc = p;
			}
			p->nextarc = NULL;

		} else { //无向图

			p = (ArcPtr) malloc(sizeof(ArcNode));
			p->adjvex = j;
			//表为空
			if(AG->vertices[i].firstarc == NULL){
				AG->vertices[i].firstarc = p;
			}
			else{
				//找最后一个表节点
				q = AG->vertices[i].firstarc;
				while(q->nextarc != NULL){
					q = q->nextarc;
				}
				q->nextarc = p;
			}
			p->nextarc = NULL;

			p = (ArcPtr) malloc(sizeof(ArcNode));
			p->adjvex = i;
			//表为空
			if(AG->vertices[j].firstarc == NULL){
				AG->vertices[j].firstarc = p;
			}
			else{
				//找最后一个表节点
				q = AG->vertices[j].firstarc;
				while(q->nextarc != NULL){
					q = q->nextarc;
				}
				q->nextarc = p;
			}
			p->nextarc = NULL;
		}

		getchar();
	}
}

/**
 * 输出图的相关信息
 */
void print_AG(ALGraph AG) {
	ArcPtr p;
	int i;
	if (AG.type == DG) {
		printf("Graph type: Direct graph\n");
	} else {
		printf("Graph type: Undirect graph\n");
	}

	printf("Graph vertex number: %d\n", AG.vexnum);
	printf("Graph arc number: %d\n", AG.arcnum);

	printf("Vertex set :\n");
	for (i = 1; i <= AG.vexnum; i++)
		printf("%c\t", AG.vertices[i].vexdata);
	printf("\nAdjacency List:\n");
	for (i = 1; i <= AG.vexnum; i++) {
		printf("%d", i);
		p = AG.vertices[i].firstarc;
		while (p != NULL) {
			printf("-->%d", p->adjvex);
			p = p->nextarc;
		}
		printf("\n");
	}
}

/**
 * 初始化顶点访问标志
 **/
void init_Visit(){
	int i;
	for(i = 0;i < MAX_VERTEX_NUM;i++)
		visit[i] = 0;
}

/**
 * 深度遍历图
 **/
void DFS_AG(ALGraph AG,int i){
	ArcPtr p;
	printf("%c\t",AG.vertices[i].vexdata);
	visit[i] = 1;
	p = AG.vertices[i].firstarc;
	while( p!= NULL ){
		if(visit[p->adjvex] == 0)
			DFS_AG(AG,p->adjvex);
		p = p->nextarc;
	}
}

int main(void) {
	ALGraph AG;

	create_AG(&AG);

	print_AG(AG);
	printf("The result of DFS:\n");
	DFS_AG(AG,1);

	return EXIT_SUCCESS;
}
时间: 2024-10-12 03:58:48

数据结构(C实现)------- 图的深度优先遍历的相关文章

数据结构?图的深度优先遍历

对于图这种数据结构,一般有两种遍历即深度优先(dfs),和广度优先(bfs),假设我们有如下这张图: 访问过程 现在假设计算0到其它点的路径,根据深度优先遍历: 1.获取0的所有邻边 1.2.5.6(默认此顺序) 2.再获取1的邻边(无),获取2的邻边(无),获取5的邻边(0,3,4) 3.0访问过,不再获取邻边:然后获取3的邻边(5,4) 4.5访问过,不再获取邻边:然后获取4的邻边(5,6) 5.5访问过,不再获取邻边:然后获取6的邻边(0,4) 6.0访问过,4被访问过,此时退到步骤2,即

数据结构 - 图的深度优先遍历(C++)

Boolean visited[MAX_VERTEX_NUM]; //访问标志数组. Status (*VisitFunc)(int v); //VisitFunc是访问函数,对图的每个顶点调用该函数. void DFSTraverse (Graph G, Status(*Visit)(int v)) //图的深度优先遍历. { VisitFunc = Visit; for(v=0; v<G.vexnum; ++v) visited[v] = FALSE; //访问标志数组初始化. for(v=

以邻接表作为存储结构的图的深度优先遍历和广度优先遍历(c++版)

一.图的存储 用邻接表法存储图,存储结构分为两部分,一部分为存储图的所有顶点的数组,另一部分为挂载在数组的每个元素后面的用来表示顶点的邻接点的链表. 1.存储顶点的结构单元为: class vnode { public: string nodename; bool visted;//进行图的遍历时用于标记图是否被访问过 node *next; vnode() { visted = false; next = NULL; } }; 链表的结构单元为: class node { public: st

图的深度优先遍历--邻接表实现

这里用邻接表实现图的深度优先遍历,采用递归实现. #include<iostream> using namespace std; #define VERTEXNUM 5//结点数 struct edgenode { int to; int weight; // 边的权值 edgenode *next; }; struct vnode { int from; edgenode *first; }; void createGraph(vnode *adjilist, int start, int

图的深度优先遍历(DFS) c++ 非递归实现

深搜算法对于程序员来讲是必会的基础,不仅要会,更要熟练.ACM竞赛中,深搜也牢牢占据着很重要的一部分.本文用显式栈(非递归)实现了图的深度优先遍历,希望大家可以相互学习. 栈实现的基本思路是将一个节点所有未被访问的“邻居”(即“一层邻居节点”)踹入栈中“待用”,然后围绕顶部节点猛攻,每个节点被访问后被踹出.读者可以自己画图分析一下,难度并不大. 代码写的比较随意,仅供参考.~ #include <iostream> #include <stack> using namespace

图的深度优先遍历DFS

图的深度优先遍历是树的前序遍历的应用,其实就是一个递归的过程,我们人为的规定一种条件,或者说一种继续遍历下去的判断条件,只要满足我们定义的这种条件,我们就遍历下去,当然,走过的节点必须记录下来,当条件不满足后,我们就return,回到上一层,换个方向继续遍历. 模板: 1 //邻接矩阵存储方式 2 bool visited[MAX]; 3 void dfs(MGraph G,int i) 4 { 5 int j; 6 visited[i]=true; 7 cout<<G.vex[i]<&

基于邻接表存储的图的深度优先遍历和广度优先遍历

一.深度优先遍历是连通图的一种遍历策略.其基本思想如下: 设x是当前被访问顶点,在对x做过访问标记后,选择一条从x出发的未检测过的边(x,y).若发现顶点y已访问过,则重新选择另一条从x出发的未检测过的边,否则沿边(x,y)到达未曾访问过的y,对y访问并将其标记为已访问过:然后从y开始搜索,直到搜索完从y出发的所有路径,即访问完所有从y出发可达的顶点之后,才回溯到顶点x,并且再选择一条从x出发的未检测过的边.上述过程直至从x出发的所有边都已检测过为止. 例如下图中: 1.从0开始,首先找到0的关

基于邻接矩阵存储的图的深度优先遍历和广度优先遍历

图的存储结构相比较线性表与树来说就复杂很多,对于线性表来说,是一对一的关系,所以用数组或者链表均可简单存放.树结构是一对多的关系,所以我们要将数组和链表的特性结合在一起才能更好的存放. 那么我们的图,是多对多的情况,另外图上的任何一个顶点都可以被看作是第一个顶点,任一顶点的邻接点之间也不存在次序关系. 仔细观察以下几张图,然后深刻领悟一下: 因为任意两个顶点之间都可能存在联系,因此无法以数据元素在内存中的物理位置来表示元素之间的关系(内存物理位置是线性的,图的元素关系是平面的). 如果用多重链表

算法题——图的深度优先遍历

原理和方法可以参考: 图的深度优先遍历 教科书上的C代码,递归: 1 //教科书方法,邻接表 2 bool visited[MAX]; 3 void visitFunc(int v); 4 5 void dfsTraverse(Graph G) 6 { 7 for(v = 0; v < G.vexnum; ++v) //初始化访问标识为false 8 visited[v] = false; 9 for(v = 0; v < G.vexnum; ++v) //深搜 10 if(!visited[

PTA 邻接矩阵存储图的深度优先遍历

6-1 邻接矩阵存储图的深度优先遍历(20 分) 试实现邻接矩阵存储图的深度优先遍历. 函数接口定义: void DFS( MGraph Graph, Vertex V, void (*Visit)(Vertex) ); 其中MGraph是邻接矩阵存储的图,定义如下: typedef struct GNode *PtrToGNode; struct GNode{ int Nv; /* 顶点数 */ int Ne; /* 边数 */ WeightType G[MaxVertexNum][MaxVe