搜索总结)(深搜和广搜)

一.我的理解


(如下只是我的理解,觉的有问题就忽略他)搜索本质就是对图的遍历,也就是考虑所有的状况后找出须要的结果。这和动态规划思想基本同样,不同的在于优化的方向不一样。搜索优化在于剪枝,也就是把不须要的状况减去从而优化(还有对结果预测如A*算法,如今还不大会之后会了在总结吧)。而动态规划则是利用空间记录重复过程的值,从而减小重复遍历而达到优化(有点像递推,从小往大推,保存小的推大时候不用再求小的)。因此动态规划本质也就是优雅的暴力(以空间换时间)。(暴力出奇迹0.0)c++

二. 基础知识


一.遍历

首先搜索虽然是对图的搜索,可是大部分图节点都是只遍历一次,这样的话图遍历也就能够看作树遍历。而树的遍历分层次遍历,先序遍历,中序遍历,后序遍历4种。而层次遍历通常借助队列完成。先中后则借助递归完成(输出节点顺序不一样,遍历过程同样)。这也就是广度优先搜索和深度优先搜索了。web

二.图的存储

图的存储分有两种:基于二维数组邻接矩阵和链表邻接表。在c++ STL提供头插法的邻接表vector,而值得一提是本身身模拟尾插邻接表的效率会大于STL提供的vector。不理解的看下图:(有几张本身画丑了点将就看吧)
邻接矩阵:这里写图片描述这里写图片描述算法

头插法邻接表:这里写图片描述这里写图片描述数组

尾插法邻接表:这里写图片描述这里写图片描述svg

三.广度优先搜索


广度优先搜索的搜索顺序就是每一个父亲节点的子节点遍历完才遍历新的节点。以上图为例,起点为v0,那么他的遍历顺序就是:v0->v1->v3->v2->v4;先遍历v0子节点v1,v3。遍历完后遍历v1的子节点v2,v4.而后发现所有节点遍历完了(若是遍历v0子节点时先遍历v3那么v0结束后先遍历v3的子节点。这和存储的结构顺序有关)。
对于算法的实现,不难看出哪一个节点先出现先遍历哪一个节点,能实现先进先出的结构固然是队列了。因此广度优先借用队列实现。STL提供queue(队列),固然你也能够直接模拟。
代码:优化

void BFS(Graph G){   ///G图,G.num节点数
    for (int v=0;v<G.num;v++) ///先将其全部顶点都设为未访问状态
        visited[v]=false;
    queue<int> Q;
    for(int v=0;v<G.num;v++) {
        if(visited[v]==false){  ///若该点没有访问
            Q.push(v);    ///将其加入到队列中
            visited[v]=true;
            while (!Q.empty()){  ///只要队列不空,遍历就没有结束
                int t =Q.front();  ///取出对头元素
                Q.pop(); 
                printf(" %d ",t+1);  ///打印节点
                for(int j=0;j<G.num;j++) ///将其未访问过的邻接点加进入队列
                    if(G.arcs[t][j]==1&&visited[j]== false) {
                        Q.push(j);
                        visited[j]=true; ///在这里要设置true为了防止重复加入!
                    }///if
            }//while
        }///if 
    }///for
}///BFS

四.深度优先搜索


深度优先搜索的搜索顺序就是每次选父节点中的一个子节点进行搜索不断下移,直到子树为空后回溯。以上图为例,起点为v0,那么他的遍历顺序就是:v0->v1->v2->v3->v4;先遍历v0子节点v1。而后遍历v1的子节点v2.接着遍历v2子节点v3,发现v3子节点都遍历过了(也就至关子节点为空)因此返回v2节点,再遍历v2子节点v4。最后一层层返回(节点都遍历了)。(有灭九族的味道,从爷爷开始杀,杀了大伯,杀大伯儿子,杀完大伯杀二伯一家,最后一个不留)。
其思想就是递归,递归至最深层,开始一层返回。而递归控制好三点就基本没问题:1.递归出口,也就是结束条件。2.递归的条件,相似递推公式找到共通部分。3.传的参数,递归不断进行参数在不断改变。
代码:ui

void DFS(Graph G,int v)
{
    visited[v]= true; ///从V开始访问,flag它
    printf("%d",v);    ///打印出节点。
    for(int j=0;j<G.num;j++) 
        if(G.arcs[v][j]==1&&visited[j]== false) ///这里能够得到V未访问过的邻接点
            DFS(G,j); ///递归调用,若是全部节点都被访问过,就回溯,而再也不调用这里的DFS
}
for (int v = 0; v < G.num; v++)
      visited[v] = false; ///刚开始都没有被访问过
 for (int v = 0; v < G.num; ++v)
      if (visited[v] == false) ///从没有访问过的第一个元素来遍历图
          DFS(G, v);