图的遍历详解(广度优先和深度优先)

数据结构的算法实践留作业啦,我选了图的遍历这一块,因为感觉比起其他的题目的话,会更加的清楚相关算法,写这篇文章是为了能够让大家更加清楚图的遍历算法,也是为了自己能够再进行一次相关知识的回顾,帮助自己答辩时顺利通关,希望答辩顺利!!!也希望看到文章的宝贝们对图的遍历这一部分更加清楚!!❤
——————————————————————————————

一、 什么是图的遍历

图的遍历是指从图中的任一顶点出发,对图中的所有顶点访问一次且只访问一次(访问一次,但不止用到一次)。 图的遍历操作和树的遍历操作功能相似二叉树的前序,中序,后序遍历,本质上也可以认为是深度优先遍历、而二叉树的层序遍历,本质上也可以认为是广度优先遍历)。图的遍历是图的一种基本操作,图的许多其它操作都是建立在遍历操作的基础之上。
就比如你想出去逛街,街上有很多店,a,b,c,d,e,f,g,要怎么才能把他们都逛呢,假如运用我们图的遍历的操作,那么就可以通过广度优先和深度优先来进行安排
图的遍历详解(广度优先和深度优先)

那么了解什么是图的遍历之后,我们来了解一下什么是广度遍历和深度遍历呢
**

二、广度遍历

**
广度优先遍历(Breadth First Search),又称为广度优先搜索,简称BFS。
是一种分层的查找过程,每向前走一步可能访问一批顶点,不像深度优先搜索那样有往回退的情况,因此它不是一个递归的算法。为了实现逐层的访问,算法必须借助一个辅助队列,以记忆正在访问的顶点的下一层顶点。
其实他本意就是,先遍历一个节点,然后遍历那个节点所连接的的周边节点,之后再一个结点一个结点的往外遍历,重复循环图的遍历详解(广度优先和深度优先)
大家还记得我上面举例子的这张图吗,如果按照广度优先遍历的话,那么访问顺序为a、b、c、d、e、f、g、h。
就是从上面一层层的遍历下来,这张图是二叉树的样式,所以可能比较容易让大家理解,那么我们现在换成图来一起做一次
图的遍历详解(广度优先和深度优先)
那么这张图,我们设从“3”开始遍历,运用广度优先的方法,那么我们所得到的遍历顺序为3,2,3,4,5,1;
**

三、深度遍历

**
https://blog.csdn.net/qq_42024195/article/details/88350544?ops_request_misc=&request_id=&biz_id=102&utm_term=%E5%B9%BF%E5%BA%A6%E4%BC%98%E5%85%88%E9%81%8D%E5%8E%86&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-3-88350544.pc_search_result_control_group&spm=1018.2226.3001.4187
这里的话,我借鉴了一下大佬的图,因为我觉得大佬这几张动画图,真的很棒,就我看的话,还是挺清楚的
首先时算法思路部分
深度优先搜索类似于树的先序遍历,具体过程如下:

准备工作:创建一个visited数组,用于记录所有被访问过的顶点。

1.从图中v0出发,访问v0。

2.找出v0的第一个未被访问的邻接点,访问该顶点。以该顶点为新顶点,重复此步骤,直至刚访问过的顶点没有未被访问的邻接点为止。

3.返回前一个访问过的仍有未被访问邻接点的顶点,继续访问该顶点的下一个未被访问领接点。

4.重复2,3步骤,直至所有顶点均被访问,搜索结束。
图的遍历详解(广度优先和深度优先)
图的遍历详解(广度优先和深度优先)
图的遍历详解(广度优先和深度优先)
图的遍历详解(广度优先和深度优先)
图的遍历详解(广度优先和深度优先)
图的遍历详解(广度优先和深度优先)
图的遍历详解(广度优先和深度优先)
图的遍历详解(广度优先和深度优先)
图的遍历详解(广度优先和深度优先)
图的遍历详解(广度优先和深度优先)
图的遍历详解(广度优先和深度优先)
图的遍历详解(广度优先和深度优先)
图的遍历详解(广度优先和深度优先)
图的遍历详解(广度优先和深度优先)
图的遍历详解(广度优先和深度优先)
**

四、代码部分

**

#include<stdio.h>
#include<stdlib.h>
#define max 20
typedef struct EdgeNode//边表结点 
{   int adjvex;        //存储顶点对应的下标   存储的是一个位置,而非具体元素,为了以后改变数据方便操作 
	struct EdgeNode *next;//链域指向下一个邻接点 
	int weight;      //权值(问题中有权值再用) 
}EdgeNode;
typedef struct VertexNode//顶点表结点 
{	char data;//存放顶点信息 
	EdgeNode *firstedge;//指向边表中第一个结点 
}VertexNode;
typedef struct
{	VertexNode adjlist[20];
	int n,e;
}GraphAdjlist;//声明图的邻接表类型 
int visited[10];//访问标志数组 (访问过赋值为1,反之为0) 

void create(GraphAdjlist *G)//创建邻接表 
{	int i,j,k;
	EdgeNode *e;
	printf("请输入顶点数和边数:");
	scanf("%d%d",&G->n,&G->e);
	getchar();//清除缓冲 
	printf("请输入顶点边号:\n");
	for(i=0;i<G->n;i++)
	{   scanf("%c",&G->adjlist[i].data);//输入顶点编号
		G->adjlist[i].firstedge=NULL;//将边表置空 
		getchar(); 
	}
	for(k=0;k<G->e;k++)
	{   printf("输入边(Vi,Vj)上的顶点序号:\n");
		scanf("%d%d",&i,&j);//头插法方便,快速   如果用尾插法需要指针遍历到尾部,太慢 
		/*使用头插法加入边表结点*/
		e=(EdgeNode *)malloc(sizeof(EdgeNode));
		e->adjvex=j;
		e->next=G->adjlist[i].firstedge; 
		G->adjlist[i].firstedge=e;
		
		e=(EdgeNode *)malloc(sizeof(EdgeNode));//因为是无向图,一条边对应两个顶点 
		e->adjvex=i;
		e->next=G->adjlist[j].firstedge; 
		G->adjlist[j].firstedge=e;	
	 } 
	printf("\n");
}
void DFS(GraphAdjlist *G,int i)
{	EdgeNode *p;
	visited[i]=1;
	printf("%c ",G->adjlist[i].data);
	p=G->adjlist[i].firstedge;
	while(p!=NULL)
	{	if(visited[p->adjvex]==0)
		  DFS(G,p->adjvex);
		p=p->next;
	}
}
void DFSTraverse(GraphAdjlist *G)
{	int i;
	for(i=0;i<G->n;i++)
	  visited[i]=0;
	for(i=0;i<G->n;i++)
	  if(visited[i]==0)
	    DFS(G,i);
}
void BFS(GraphAdjlist *G,int v)
{	EdgeNode *p;
	int queue[max],front=0,rear=0;//定义循环队列并初始化 
	int w,i;
	for(i=0;i<G->n;i++)//标志数组初始化 
	    visited[i]=0;
	printf("%2c",G->adjlist[v].data);
	visited[v]=1;
	rear=(rear+1)%max;
	queue[rear]=v;
	while(front!=rear)
	{	front=(front+1)%max;
		w=queue[front];
		p=G->adjlist[w].firstedge;
		while(p!=NULL)
		{	if(visited[p->adjvex]==0)
			{	printf("%2c",G->adjlist[p->adjvex].data);
				visited[p->adjvex]=1;
				rear=(rear+1)%max;
				queue[rear]=p->adjvex;
			}
			p=p->next;
		}
	}
	printf("\n");
}
int main()//A B C D E
{	GraphAdjlist G;
	create(&G);
	printf("深度优先遍历:");
	DFSTraverse(&G);
		printf("广度优先遍历:");
	BFS(&G,0); 
	return 0;
}


明天就要答辩了,所以比较赶,时间不太来的及,大家先凑合者看吧,等答辩完我再补

上一篇:C++ 常用设计模式学习——工厂模式


下一篇:图的遍历