关于图的存储在上一篇文章中已经讲述,在这里不在赘述。下面我们介绍图的深度优先搜索遍历(DFS)。

深度优先搜索遍历实在访问了顶点vi后,访问vi的一个邻接点vj;访问vj之后,又访问vj的一个邻接点,依次类推,尽可能向纵深方向搜索,所以称为深度优先搜索遍历。显然这种搜索方法具有递归的性质。图的BFS和树的搜索遍历很类似,只是其存储方式不同。

        其基本思想为:从图中某一顶点vi出发,访问此顶点,并进行标记,然后依次搜索vi的每个邻接点vj;若vj未被访问过,则对vj进行访问和标记,然后依次搜索vj的每个邻接点; 若vj的邻接点未被访问过,则访问vj的邻接点,并进行标记,直到图中和vi有路径相通的顶点都被访问。若图中尚有顶点未被访问过(非连通的情况下),则另选图中的一个未被访问的顶点作为出发点,重复上述过程,直到图中所有顶点都被访问为止。

在下面的程序中,假设图如下所示:

A B C D E对应的序号分别为0 1 2 3 4.上图的轨迹为一种深度优先搜索遍历。

具体的程序实现如下:

#include<stdio.h>
#include<stdlib.h>
#define N 5

typedef struct
{
	char vexs[N];//顶点数组
	int arcs[N][N];//邻接矩阵
}graph;

//图的两种存储方法的结构体
typedef struct Node
{
	int adjvex;
	struct Node *next;
}edgenode;

typedef struct
{
	char vertex;
	edgenode *link;
}vexnode;

//队列的结构体
typedef struct node
{
	int data;
	struct node *next;
}linklist;

typedef struct
{
	linklist *front,*rear;
}linkqueue;

void DFS_matrix(graph g,int i,int visited[N]);//图按照邻接矩阵存储时的深度优先搜索遍历
void DFS_AdjTable(vexnode ga[N],int i,int visited[N]);//图按照邻接矩表存储时的深度优先搜索遍历

void SetNull(linkqueue *q)//置空
{
	q->front=(linklist *)malloc(sizeof(linklist));
	q->front->next=NULL;
	q->rear=q->front;
}

int Empty(linkqueue *q)//判空
{
	if(q->front==q->rear)
		return 1;
	else
		return 0;
}

int Front(linkqueue *q)//取队头元素
{
	if(Empty(q))
	{
		printf("queue is empty!");
		return -1;
	}
	else
		return q->front->next->data;
}

void ENqueue(linkqueue *q,int x)//入队
{
	linklist * newnode=(linklist *)malloc(sizeof(linklist));
    q->rear->next=newnode;
	q->rear=newnode;
	q->rear->data=x;
	q->rear->next=NULL;

}

int DEqueue(linkqueue *q)//出队
{
	int temp;
	linklist *s;
	if(Empty(q))
	{
		printf("queue is empty!");
		return -1;
	}
	else
	{
		s=q->front->next;
		if(s->next==NULL)
		{
			q->front->next=NULL;
			q->rear=q->front;
		}
		else
			q->front->next=s->next;
		temp=s->data;
		return temp;
	}
}

void CreateAdjTable(vexnode ga[N],int e)//创建邻接表
{
	int i,j,k;
	edgenode *s;
	printf("\n输入顶点的内容:");
	for(i=0;i<N;i++)
	{
		//scanf("\n%c",ga[i].vertex);

		ga[i].vertex=getchar();

		ga[i].link=NULL;//初始化
	}
	printf("\n");
	for(k=0;k<e;k++)
	{
		printf("输入边的两个顶点的序号:");
		scanf("%d%d",&i,&j);//读入边的两个顶点的序号
		s=(edgenode *)malloc(sizeof(edgenode));
		s->adjvex=j;
		s->next=ga[i].link;
		ga[i].link=s;

		s=(edgenode *)malloc(sizeof(edgenode));
		s->adjvex=i;
		s->next=ga[j].link;
		ga[j].link=s;

	}
}

void main()
{
	graph g;
	int visited[5]={0};//初始化
	int visited1[5]={0};
	g.vexs[0]='A';
	g.vexs[1]='B';
	g.vexs[2]='C';
	g.vexs[3]='D';
	g.vexs[4]='E';
	int a[5][5]={{0,1,0,1,1},{ 1,0,1,0,1},{ 0,1,0,0,0},{ 1,0,0,0,0},{ 1,1,0,0,0}};
	for(int i=0;i<5;i++)
		for(int j=0;j<5;j++)
			g.arcs[i][j]=a[i][j];
	printf("图按照邻接矩阵存储时的深度优先搜索遍历:\n");
	DFS_matrix(g,0,visited);
	vexnode ga[N];
	CreateAdjTable(ga,5);//5为边的条数
		printf("图按照邻接表存储时的深度优先搜索遍历:\n");
    DFS_AdjTable(ga,0,visited1);//0为开始的顶点的序号

}

void DFS_matrix(graph g,int i,int visited[N])
{
	printf("%c\n",g.vexs[i]);
	visited[i]=1;
	for(int j=0;j<N;j++)
		if(g.arcs[i][j]==1&&visited[j]==0)//是否有未被访问的邻接点
			DFS_matrix(g,j,visited);//递归
}

void DFS_AdjTable(vexnode ga[N],int i,int visited[N])
{
	edgenode *p;
	printf("%c\n",ga[i].vertex);
	visited[i]=1;
	p=ga[i].link;
	while(p!=NULL)//p是否为空
	{
		if(visited[p->adjvex]==0)
			DFS_AdjTable(ga,p->adjvex,visited);
		p=p->next;
	}
}

其结果如下:

从上面可以看出,两种方式的结果不同,但都是正确的,因为这与邻接点访问的顺序有关。

注:如果程序出错,可能是使用的开发平台版本不同,请点击如下链接: 解释说明


原文:http://blog.csdn.net/tengweitw/article/details/17248643

作者:nineheadedbird

【算法导论】图的深度优先搜索遍历(DFS)的更多相关文章

  1. 【算法导论】图的广度优先搜索遍历(BFS)

    图的存储方法:邻接矩阵.邻接表 例如:有一个图如下所示(该图也作为程序的实例): 则上图用邻接矩阵可以表示为: 用邻接表可以表示如下: 邻接矩阵可以很容易的用二维数组表示,下面主要看看怎样构成邻接表: ...

  2. 图的深度优先搜索dfs

    图的深度优先搜索: 1.将最初访问的顶点压入栈: 2.只要栈中仍有顶点,就循环进行下述操作: (1)访问栈顶部的顶点u: (2)从当前访问的顶点u 移动至顶点v 时,将v 压入栈.如果当前顶点u 不存 ...

  3. [算法入门]——深度优先搜索(DFS)

    深度优先搜索(DFS) 深度优先搜索叫DFS(Depth First Search).OK,那么什么是深度优先搜索呢?_? 样例: 举个例子,你在一个方格网络中,可以简单理解为我们的地图,要从A点到B ...

  4. 采用邻接矩阵表示图的深度优先搜索遍历(与深度优先搜索遍历连通图的递归算法仅仅是DFS的遍历方式变了)

    //采用邻接矩阵表示图的深度优先搜索遍历(与深度优先搜索遍历连通图的递归算法仅仅是DFS的遍历方式变了) #include <iostream> using namespace std; ...

  5. 深度优先搜索(DFS)

    定义: (维基百科:https://en.wikipedia.org/wiki/Depth-first_search) 深度优先搜索算法(Depth-First-Search),是搜索算法的一种.是沿 ...

  6. 深度优先搜索(dfs)与出题感想

    在3月23号的广度优先搜索(bfs)博客里,我有提到写一篇深搜博客,今天来把这个坑填上. 第一部分:深度优先搜索(dfs) 以上来自百度百科. 简单来说,深度优先搜索算法就是——穷举法,即枚举所有情况 ...

  7. 深度优先搜索(DFS)与广度优先搜索(BFS)的Java实现

    1.基础部分 在图中实现最基本的操作之一就是搜索从一个指定顶点可以到达哪些顶点,比如从武汉出发的高铁可以到达哪些城市,一些城市可以直达,一些城市不能直达.现在有一份全国高铁模拟图,要从某个城市(顶点) ...

  8. 深度优先搜索(DFS)和广度优先搜索(BFS)

    深度优先搜索(DFS) 广度优先搜索(BFS) 1.介绍 广度优先搜索(BFS)是图的另一种遍历方式,与DFS相对,是以广度优先进行搜索.简言之就是先访问图的顶点,然后广度优先访问其邻接点,然后再依次 ...

  9. Leetcode之深度优先搜索(DFS)专题-130. 被围绕的区域(Surrounded Regions)

    Leetcode之深度优先搜索(DFS)专题-130. 被围绕的区域(Surrounded Regions) 深度优先搜索的解题详细介绍,点击 给定一个二维的矩阵,包含 'X' 和 'O'(字母 O) ...

随机推荐

  1. Android开发技巧——Camera拍照功能

    本篇是我对开发项目的拍照功能过程中,对Camera拍照使用的总结.由于camera2是在api level 21(5.0.1)才引入的,而Camera到6.0仍可使用,所以暂未考虑camera2. 文 ...

  2. 【Android】给Android Studio设置代理

    先打开我们的Android Studio,点击工具栏的file下的settings,如下图 之后再搜索框上面输入Proxy,然后按第四步提示点击,如下图 之后就进入了设置代理的界面了,如下图 默认情况 ...

  3. AJAX编程实践

    ---------------------------------------------------------------------------------------------------- ...

  4. springMVC源码分析--SimpleControllerHandlerAdapter(三)

    上一篇博客springMVC源码分析--HandlerAdapter(一)中我们主要介绍了一下HandlerAdapter接口相关的内容,实现类及其在DispatcherServlet中执行的顺序,接 ...

  5. Java程序员必须掌握的线程知识-Callable和Future

    Callable和Future出现的原因 创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需 ...

  6. Android开发之Intent.Action 各种Action的常见作用

    1 Intent.ACTION_MAIN String: android.intent.action.MAIN 标识Activity为一个程序的开始.比较常用. Input:nothing Outpu ...

  7. Dialog样式的Activity

    效果图: 设置全屏模式: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInst ...

  8. memcached实战系列(一)memcached安装

    下载并安装Memcached服务器端 我用的是cenos6.5 64位系统. libevent是个程序库,它将Linux的epoll.BSD类操作系统的kqueue等事件处理功能封装成统一的接口,具有 ...

  9. socket系列之服务器端socket——ServerSocket类

    一般地,Socket可分为TCP套接字和UDP套接字,再进一步,还可以被分为服务器端套接字跟客户端套接字.这节我们先关注TCP套接字的服务器端socket,Java中ServerSocket类与之相对 ...

  10. linux中查看现在使用的shell是ksh还是bash?以及怎样修改?

    查看系统支持的shell: cat  /etc/shells 查看现在使用的shell:  修改默认shell: 另外,修改了系统默认shell之后不会立即生效,之后再次登录系统修改的shell才会生 ...