第二周总结(关于基本搜索算法)

这周的主题是基本的搜索算法,基于bfs(广度搜索)和dfs(深度搜索)来实现的

在这里简单介绍以下dfs(深度搜索)算法

这里的关键点是递归和回溯

深度优先搜索算法(DFS)是一种用于遍历或者搜索树或图的算法,沿着一些树遍历树的结点,尽可能深的搜索树的分支,当节点的所在边都被探索过,搜索将回溯到发现结点v的那条边的起始结点.这一过程持续到发现原节点可以到达的所有节点位置。

深度优先搜索的步骤分为 1.递归下去 2.回溯上来。顾名思义,深度优先,则是以深度为准则,先一条路走到底,直到达到目标。这里称之为递归下去。

否则既没有达到目标又无路可走了,那么则退回到上一步的状态,走其他路。这便是回溯上来。

下面来结合具体例子来进行理解

这里写图片描述

假设按照以下的顺序来搜索:

1.V0->V1->V4,此时到底尽头,仍然到不了V6,于是原路返回到V1去搜索其他路径;

2.返回到V1后既搜索V2,于是搜索路径是V0->V1->V2->V6,,找到目标节点,返回有解。

这样搜索只是2步就到达了,但是如果用BFS的话就需要多几步。

DFS的核心伪代码(C语言递归方式)

//它的前置条件是标记已经走过的路径,让book全部初始化为0
//并且知道起始状态和结束状态
void dfs(int step)
{

   for(i = 1; i <= n ;i++)
   {
      if(book[i] == 0)
      {
        a[step] = i;  //a数组已经实现
        book[i]= 1; //将book数组设为1,表示已经走过
       dfs(step+1);//这里通过函数递归的方式,来尝试下一个节点
        book[i] =0 ;//这条语句和上条语句很重要,是dfs的关键,回溯的思想,dfs通过递归调用自己,来进行下一步的尝试,如果可以就开始执行下一部分
     }
     return ;
}

DFS很难保存最短路径,它采用了回溯的方式来进行,一条路经走到头,直到不能走的时候然后返回上次,DFS一般用来求有几种方式阿什么的问题,最值问题一般来使用BFS来进行求解的

DFS另一个有用的性质是: 对于二叉树而言, dfs得到的节点顺序正是其前序遍历(preorder traversal)的顺序.

其实前序遍历的定义就相当于是一个递归版本的dfs了:
[preorder(node)] = node.val + [preorder(node.left)] + [preorder(node.right)]

DFS有两种实现方式,一种是利用栈来实现,另外一种是通过递归的方式来实现

接下来,简单说一下BFS算法(广度优先算法)
BFS算法一般是需要和队列结合起来使用的,是一种盲目的搜索法,同时也叫横向优先算法,它把每个节点能访问到的所有位置以队列的形式存储,放入到这个容器中

首先以一个未被访问过的顶点作为起始顶点,访问其所有相邻的顶点,然后对每个相邻的顶点,再访问它们相邻的未被访问过的顶点,直到所有顶点都被访问过,遍历结束。

在这里也以例子来进行解释一下
这里写图片描述

如果说以v0点作为开始,那么在第一次执行操作之后应该在队列中存储v1,v2,v3这三种方式,从v0中选择一种,如果选择v3接下来应该存储的是v0,v1,v5这三种,但是因为之前已经做过标记,如果在这里仅仅存储的是v5

实现方式:
1.首先取起始条件放入到队列中,
2.从队列中取出队首节点,检测它是不是目标

  • 如果找到目标,就结束搜索并且向主函数传达结果

  • 不然的话,进行出队

3 如果队列为空,说明图检查过没有结果

下面给出C语言实现方式

int book[1001],que[1001],head,tail;//head和end模拟队列的队首和队尾位置
head=1;
tail=1;
//从1号顶点出发,将1号顶点加入队列
que[tail]=1;
tail++;
book[1]=1;//标记1号顶点已访问
//BFS核心部分
while(head<tail)//当队列不为空的时候循环
{
    cur=que[head];
    for(i=1;i<=n;i++)
    {
        //判断从顶点cur到顶点i是否有边,并判断顶点i是否已经被访问过
        if(e[cur][i]!=INT_MAX && book[i]==0)
        {
        //将顶点i加入队列
            que[tail]=i;
            tail++;
            book[i]=1;
        }
        //如果tail大于n,说明所有顶点都被访问过
        if(tail>n)
        {
            break;
        }
    }
    //当一个顶点拓展结束后,要将head++,相当于从队首删除该顶点
    head++;
}

下章开始写这周的算法题

猜你喜欢

转载自blog.csdn.net/dream0130__/article/details/81411726
今日推荐