深度优先搜索和广度优先搜索

深度优先搜索和广度优先搜索

​ 在人工智能的运筹学的领域中求解与图相关的应用中,这两个算法被证明是非常有用的,而且,如需高效地研究图的基本性质,例如图的连通性以及图是否存在环,这些算法也是必不可少的。

深度优先搜索

​ 深度优先搜索可以从任意顶点开始访问图的顶点,然后把该顶点标记为已访问,在每次迭代中,该算法紧接着处理与当前顶点邻接的未访问的顶点。这个过程一直持续,直到遇到一个终点——该顶点的所有邻接点都已经被访问过。在该终点上,该算法沿着来路后退一条边,并试着继续从哪里访问未访问的顶点,在后退到起始顶点,并起始顶点也是一个终点时,该算法最终停了下来。这样起始顶点所在的连通分量的所有顶点都被访问过了。如果未访问的顶点仍然存在,该算法必须从其中任一顶点开始,重复上述过程。

​ 用一个来跟踪深度优先搜索的操作是比较方便的。在第一次访问一个顶点时,我们把该顶点入栈,当它成为一个终点时,我们把它出栈。

Java实现深度优先搜索:

boolean [] visited;
/**
* @Description: 从n开始进行的深度优先遍历
* @return: 返回结果
* @Author: Mr.Gao
* @Date: 2021/2/15
*/
public void result(int n,DenseGraph denseGraph){
    int node = denseGraph.findNode();
    visited = new boolean[node];

    Stack<Integer> stack = new Stack<>();
    stack.push(n);
    while(!stack.empty()){
        int temp = stack.pop();
        visited[temp]=true;
        System.out.print(temp+" ");
        for (int i = 0; i < node; i++) {
            if(visited[i]==false&&denseGraph.getG()[temp][i]==true){
                stack.push(i);
            }
        }
    }
}
  • 这里的DenseGraph是我们实现的稠密图的类。专门用于实现稠密图。
稠密图代码:
/**
 * @program:算法库
 * @description:稠密图的创建,使用邻接矩阵
 */
public class DenseGraph {
    private int edge;           //边数
    private int node;           //节点数
    private boolean direction;  //是否为有向图
    private boolean[][] g;      //图的具体数据
    public boolean[][] getG() {
        return g;
    }
    public DenseGraph(int node, boolean direction){
        assert node>=0;         //一个断言
        
        this.node = node;
        this.direction = direction;
        this.g = new boolean[node][node];
    }

    //返回边数
    public int findEdge(){
        return edge;
    }
    //返回节点数
    public int findNode(){
        return node;
    }
    //为图添加一条边
    public void addEdge(int p,int q){
        assert p>=0&&p<node;
        assert q>=0&&q<node;

        if(hasEdge(p,q)){
            return;
        }
        g[p][q]=true;
        if(!direction){
            g[q][p]=true;
        }
        edge++;
    }
    //检验p到q是否有一条边
    public boolean hasEdge(int p,int q){
        assert p>=0&&p<node;
        assert q>=0&&q<node;
        return g[p][q];
    }
}
  • 稠密图我们使用邻接矩阵实现,而稀疏图我们使用邻接链表进行实现
稀疏图的类代码:
import java.util.Vector;

/**
 * @program:算法库
 * @description:稀疏图的创建,使用邻接链表,这里我们规定从自己到自己有一条默认路径。
 */

public class SparseGraph {
    private int node;           //节点数
    private int edge;           //边数
    private boolean direction;  //是否为有向图
    private Vector<Integer>[] g;//图的具体数据
    
    public SparseGraph(int node,boolean direction){
        assert node>=0;         //设置一个断言
        this.node = node;
        this.direction = direction;
        this.g = (Vector<Integer>[]) new Vector[node];
        for (int i = 0; i < node; i++) {
            g[i] = new Vector<Integer>();
        }
    }
    
    //返回边的个数
    public int findEdge(){
        return edge;
    }
    //返回节点个数
    public int findNode(){
        return node;
    }
    //添加一条从p到q的边
    public void addEdge(int p ,int q){
        assert p>=0&&p<node;
        assert q>=0&&q<node;
        assert p!=q;

        if(!hasEdge(p,q)){
            g[p].add(q);
            if(!direction){
                g[q].add(p);
            }
        }
        edge++;
    }
    public boolean hasEdge(int p,int q){
        assert p>=0&&p<node;
        assert q>=0&&q<node;

        if(p==q){
            return true;
        }
        for (int i = 0; i < g[p].size(); i++) {
            if(g[p].elementAt(i)==q){
                return true;
            }
        }
        return false;
    }

}

广度优先搜索:

​ 如果说深度优先搜索表现出来的是一种勇气,那么广度优先搜索表现出来的就是一种严谨。它按照一种同心圆的方式,首先访问所有和初始顶点邻接的顶点,然后是离它两条边的所有未访问顶点,以此类推,直到所有与初始顶点同在一个连通分量中的顶点都访问过了为止,如果仍然存在未被访问的顶点,该算法必须从图的其他连通分量中的任意顶点重新开始。

​ 使用队列来跟踪广度优先搜索的查找是方便的。该队列先从遍历的初始顶点开始,将该顶点标记为已访问,在每次迭代中,该算法找出所有和队头顶点邻接的未访问顶点,把它们标记为已访问,再把它们入队。然后将队头顶点从队列中移走。

Java实现:

boolean[] visited;
/**
* @Description: 使用邻接矩阵实现广度优先搜索
* @return:  返回结果
* @Author: Mr.Gao
* @Date: 2021/2/15
*/
public void result(int n,DenseGraph denseGraph){

    int node = denseGraph.findNode();
    visited = new boolean[node];
    Queue<Integer> queue = new LinkedList<>();
    queue.add(n);

    while(!queue.isEmpty()){
        int temp = queue.poll();
        System.out.print(temp+" ");
        visited[temp] = true;
        for (int i = 0; i < node; i++) {
            if(visited[i]==false&&denseGraph.getG()[temp][i]==true){
                queue.add(i);
            }
        }
    }
}
  • 最后附上深度优先搜索和广度优先搜索的主要性质
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WalmCVdw-1619137227209)(F:/%E7%AC%94%E8%AE%B0%E5%9B%BE%E7%89%87%E4%B8%93%E7%94%A8%E6%96%87%E4%BB%B6%E5%A4%B9/image-20210215194610007.png)]
  • 我太菜了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值