图伦---(画图理解DFS)

1.原图与邻接表存储图

     在这里插入图片描述

顶点邻接关系
V1V2----V3
V2V1----V4----V5
V3V1----V6----V7
V4V2----V5----V8
V5V2----V4
V6V3
V7V3
V8V4

2.手算图的DFS搜索

第一次开始直接访问V1,V1的邻接顶点是V2、V3

第二次访问顶点V1的第一个邻接顶点V2,V2当前没有访问过,可以访问,访问V2,V2的邻接顶点是V1、V4、V5

第三次访问顶点V2的第一个邻接顶点V1,V1已经在第一次时候访问过了,不能访问,接着访问顶点V2第二个邻接点V4,V4当前没有访问过,可以访问,访问V4,V4的邻接顶点是V2、V5、V8

第四次访问顶点V4的第一个邻接顶点V2,V2已经在第二次的时候访问过了,不能访问,接着访问V4的第二个邻接点V5,V5当前没有访问过,可以访问,访问V5,V5的邻接顶点是V2、V4

第五次访问顶点V5的第一个邻接顶点V2,V2已经在第二次的时候访问过了,不能访问,接着访问V5的第二个邻接点V4,V4已经在第三次访问过了,也不能访问,最后V5没有其他邻接点,接着回退到第四次,当前的顶点是V4,当前访问到的邻接点是V5,接着访问V4的下一个邻接点是V8,V8没有访问过,可以访问,访问V8,V8的邻接顶点是V4

第六次访问顶点V8的第一个邻接顶点V4,V4已经在第三次访问过了,不能访问,此时的V8所有邻接顶点访问完成,回退到第四次,当前的顶点是V4,当前访问到的邻接顶点是V8,接着发现V4所有邻接顶点访问完成,继续回退到第三次,当前顶点是V2,当前访问的邻接点是V4,接着访问V2的第三个邻接顶点V5,发现V5在第四次的时候访问过了,继续回退到第二次,当前顶点是V1,当前所访问到的邻接顶点是V2,接着访问V1的第二个邻接顶点V3,发现没有访问,访问V3,顶点V3的邻接顶点是V1、V6、V7

第七次访问顶点V3的第一个邻接顶点V1,发现V1在第一次的时候访问过来,不能访问,接着访问V3的第二个邻接顶点V6,没有访问,访问V6,顶点V6的邻接顶点是V3、V7

第八次访问顶点V6的第一个邻接顶点V3,发现V3在第六次的时候访问过了,不能访问,接着访问顶点V6的第二个邻接顶点V7,没有访问,访问V7,顶点V7的邻接顶点是V3、V6

第九次访问顶点V7的第一个邻接顶点是V3,发现V3在第六次已经访问过了不能访问,接着访问顶点V7第二个邻接顶点V6,发现V6在第七次的时候访问过了,所以回退到第八次,当前顶点是V6,当前所访问的邻接顶点是V7,发现V7是顶点V6的最后一个邻接顶点,所以继续回退到第七次,当前顶点是V3,当前所访问的邻接顶点是V6,接着访问顶点V3的下一个顶点,访问顶点V3的第三个顶点V7,发现V7已经访问过了且V7是顶点V3的最后一个邻接顶点,所以继续回退到第6次,当前的顶点是V1,当前所访问的邻接顶点是V3,且发现邻接点V3是顶点V1的最后一个邻接点,所以继续回退,最后V3是访问的最后一个顶点,退出程序.

所以以顶点V1开始DFS搜索,访问的顺序为:V1 V2 V4 V5 V8 V3 V6 V7

3.伪代码:

1.访问顶点V,同时visited[V]设置访问过的标志1
2.循环遍历每一个顶点的所有邻接点 {
  //如果当前顶点没有访问过,并且该邻接点是该顶点的邻接点
  //那么就dfs搜索吧该邻接点重新作为顶点去搜索,下一次查找该顶点的邻接点
}

4.dfs图搜索总结

对于dfs搜索肯定是在循环中进行调用递归的算法,每一次去搜索顶点的邻接点,如果找到了该顶点的邻接点,那么dfs到达下一层,此时的顶点是作为上一次的邻接点,继续这样循环操作,就是一直寻找顶点的邻接点,调用递归,邻接点变成顶点,又继续搜索此时的顶点的邻接点,一直搜索每一个顶点的邻接点,当出现了这种情况下就停止搜索,此时的循环就起到了很好的作用,当dfs搜索到某一层的时候,此时没有找到该顶点的邻接点,那么返回上一层,搜索该顶点的下一个邻接点,如图所示。

                 在这里插入图片描述
有三个顶点,ABC,其中A存储邻接点B和C,如果这个图按照DFS搜索。
1.先访问A点,设置A已经访问过的标志
2.在循环中进行遍历每一个顶点的邻接点,此时发现A的第一个邻接点是B,然后递归调用下一层,访问B,设置B访问过的标志,接着发现B没有邻接点,此时该层结束,返回到上一层去,由于是在循环中进行的,此时的递归结束后,循环查找A的下一个邻接点,那么就是C。
这就是循环的好处,每一次DFS结束后,会跳到上一次从哪一个邻接点调用的地方去,循环到该顶点的下一个邻接点。

5.邻接矩阵与DFS算法

在这里插入图片描述

#include <stdio.h>
typedef char VertextType;
#define MAX_VERTEXT 10
#pragma warning(disable:4996)
//定义一个图
typedef struct Graph {
	VertextType adj[MAX_VERTEXT];         //顶点
	int arc[MAX_VERTEXT][MAX_VERTEXT];    //邻接矩阵
	int vexnum, arcnum;                   //顶点数  弧数
}MGraph;
//确定顶点位置
int LocateVertext(MGraph* G, VertextType v) {
	int i = 0;
	while (i < G->vexnum && v != G->adj[i]) i++;
	if (G->adj[i] == v) return i;
	else return -1;
}
//用邻接矩阵创建图
void CreateDN(MGraph* G) {
	int i, j, k, weight;
	VertextType v1, v2;
	printf("输入顶点数和弧数:");
	scanf("%d %d", &G->vexnum, &G->arcnum);
	getchar();
	printf("输入%d个顶点:", G->vexnum);
	for (i = 0; i < G->vexnum; i++) {
		scanf("%c", &G->adj[i]);
		getchar();
	}
	//初始化邻接矩阵
	for (i = 0; i < G->vexnum; i++) {
		for (j = 0; j < G->vexnum; j++) {
			G->arc[i][j] = 0;
		}
	}
	for (k = 0; k < G->arcnum; k++) {
		printf("输入第%d组顶点和权值:", k + 1);
		scanf("%c %c %d", &v1, &v2, &weight);
		getchar();
		i = LocateVertext(G, v1);
		j = LocateVertext(G, v2);
		if (i != -1 && j != -1) {
			G->arc[i][j] = weight;
			G->arc[j][i] = weight;
		}
	}
}
//显示邻接矩阵
void display_Graph(MGraph* G) {
	int i, j;
	printf("   ");
	for (i = 0; i < G->vexnum; i++) {
		printf("%3c", G->adj[i]);
	}
	printf("\n");
	for (i = 0; i < G->vexnum; i++) {
		printf("%3c", G->adj[i]);
		for (j = 0; j < G->vexnum; j++) {
			printf("%3d", G->arc[i][j]);
		}
		printf("\n");
	}
}

//显示各个顶点与邻接点关系
void display_vex(MGraph* G) {
	int i, j;
	for (i = 0; i < G->vexnum; i++) {
		printf("%3c的邻接点:", G->adj[i]);
		for (j = 0; j < G->vexnum; j++) {
			if (G->arc[i][j] != 0) {
				printf("%3c", G->adj[j]);
			}
		}
		printf("\n");
	}
}

//设置访问数组
int visited[MAX_VERTEXT];
void DFS(MGraph G, int v) {
	printf("%c ", G.adj[v]);
	visited[v] = 1; //设置访问标志
	for (int i = 0; i < G.vexnum; i++) {
		//如果当前顶点没有访问过,并且该邻接点是该顶点的邻接点
		if (!visited[i] && G.arc[v][i] != 0) DFS(G, i);
	}
}

int main() {
	MGraph G;
	int i, j;
	CreateDN(&G);      //创建邻接矩阵
	printf("\n邻接矩阵表示\n");
	display_Graph(&G); //显示邻接矩阵
	printf("\n显示各个顶点与邻接点关系\n");
	display_vex(&G);
	printf("DFS搜索图的顶点:");
	DFS(G, 0);
	return 0;
}
/*
邻接矩阵运行接过
输入顶点数和弧数:5 6
输入5个顶点:A B C D E
输入第1组顶点和权值:A B 2
输入第2组顶点和权值:A C 4
输入第3组顶点和权值:A E 9
输入第4组顶点和权值:B E 3
输入第5组顶点和权值:C D 6
输入第6组顶点和权值:D E 5

邻接矩阵表示
	 A  B  C  D  E
  A  0  2  4  0  9
  B  2  0  0  0  3
  C  4  0  0  6  0
  D  0  0  6  0  5
  E  9  3  0  5  0

显示各个顶点与邻接点关系
  A的邻接点:  B  C  E
  B的邻接点:  A  E
  C的邻接点:  A  D
  D的邻接点:  C  E
  E的邻接点:  A  B  D

DFS搜索图的顶点:A B E D C
*/

6.邻接表与DFS

#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
#define MAX_VERTEXT 10
typedef char VertexType;
typedef struct ArcNode {
	VertexType vex;       //顶点
	int adjvex;           //邻接点序号
	struct ArcNode* next; //指向下一个邻接点的指针域
}ArcNode;
typedef struct VertexNode { //定义表头
	VertexType data;
	struct ArcNode* next;
}VertexNode;
typedef struct {
	VertexNode vertex[MAX_VERTEXT];  //顶点
	int arcnum, vexnum;              //弧数 顶点
}MGraph;

//查找
int loadcateVertex(MGraph* G, VertexType v) {
	int i = 0;
	while (i < G->vexnum && G->vertex[i].data != v) i++;
	if (G->vertex[i].data == v) return i;
	else return -1;
}

//创建邻接表
void Create(MGraph* G) {
	ArcNode* s;
	VertexType v1, v2;
	int weight;
	int i, j;
	int k1, k2;
	printf("输入顶点数和弧数:");
	scanf("%d %d", &G->vexnum, &G->arcnum);
	getchar();
	printf("输入%d个顶点:", G->vexnum);
	for (i = 0; i < G->vexnum; i++) {
		scanf("%c", &G->vertex[i].data);
		getchar();
		G->vertex[i].next = NULL;
	}

	for (i = 0; i < G->arcnum; i++) {
		printf("输入第一个顶点和邻接点和权值:");
		scanf("%c %c %d", &v1, &v2, &weight);
		getchar();
		k1 = loadcateVertex(G, v1);
		k2 = loadcateVertex(G, v2);

		s = (ArcNode*)malloc(sizeof(ArcNode));
		s->vex = v2;    //初始化顶点
		s->adjvex = k2; //初始化序号
		//头插法连接到顶点表中
		s->next = G->vertex[k1].next;
		G->vertex[k1].next = s;

		s = (ArcNode*)malloc(sizeof(ArcNode));
		s->vex = v1;    //初始化顶点
		s->adjvex = k1; //初始化序号
		//头插法连接到顶点表中
		s->next = G->vertex[k2].next;
		G->vertex[k2].next = s;
	}
}
//访问各个顶点的邻接表
void display_vertex(MGraph* G) {
	ArcNode* s = NULL;
	int i;
	for (i = 0; i < G->vexnum; i++) {
		s = G->vertex[i].next;
		printf(" %c的邻接点:", G->vertex[i].data);
		while (s != NULL) {
			printf("%c ", s->vex);
			s = s->next;
		}
		printf("\n");
	}
}
int visided[MAX_VERTEXT]; //设置访问标志
void DFS(MGraph* G, int v) {
	ArcNode* s = NULL;
	if (!visided[v]) printf("%c ", G->vertex[v].data);
	visided[v] = 1;

	s = G->vertex[v].next;
	while (s != NULL) {
		//判断当前邻接点是否访问
		if (!visided[s->adjvex]) DFS(G, s->adjvex);
		s = s->next;
	}
	
}
int main() {
	MGraph G;
	Create(&G);                //创建邻接表
	display_vertex(&G);        //显示各个顶点邻接信息
	printf("DFS搜索结果:");
	DFS(&G, 0);
	return 0;
}
/*
输入顶点数和弧数:5 6
输入5个顶点:A B C D E
输入第一个顶点和邻接点和权值:A B 2
输入第一个顶点和邻接点和权值:A C 4
输入第一个顶点和邻接点和权值:A E 9
输入第一个顶点和邻接点和权值:B E 3
输入第一个顶点和邻接点和权值:C D 6
输入第一个顶点和邻接点和权值:D E 5
 A的邻接点:E C B
 B的邻接点:E A
 C的邻接点:D A
 D的邻接点:E C
 E的邻接点:D B A
 DFS搜索结果:A E D C B
*/

由于邻接表采用头插法结构的链表,所以利用DFS搜索的结果与邻接矩阵的DFS搜索的结果不一样
邻接矩阵DFS:A B E D C
邻接表DFS:A E D C B

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值