深度优先搜索(DFS)

所谓深度优先搜索,是从"图"中的一个顶点出发,每次遍历当前访问顶点的临界点,一直到访问的顶点没有未被访问过的临界点为止。然后采用依次回退的方式,查看来的路上每一个顶点是否有其它未被访问的临界点。访问完成后,判断图中的顶点是否已经全部遍历完成,如果没有,以未访问的顶点为起始点,重复上述过程。(百度)

(不了解图的可以先看看这篇文章)

深度优先搜索(DFS) (深度优先搜索通过栈来实现)

注:深度优先搜索(DFS)是图搜索方法的一种

规则如下: 

规则1:如果可能,访问一个邻接的未访问顶点,标记它,并将它放入栈中。

规则2:当不能执行规则 1 时,如果栈不为空,就从栈中弹出一个顶点。

规则3:如果不能执行规则 1 和规则 2 时,就完成了整个搜索过程。

对于上图,应用深度优先搜索如下:
假设选取 A 顶点为起始点,并且按照字母优先顺序进行访问,
那么应用规则 1 ,接下来访问顶点 B,然后标记它,并将它放入栈中;
再次应用规则 1,接下来访问顶点 F,
再次应用规则 1,访问顶点 H。
我们这时候发现,没有 H 顶点的邻接点了,这时候应用规则 2,
从栈中弹出 H,这时候回到了顶点 F,
但是我们发现 F 也除了 H 也没有与之邻接且未访问的顶点了,那么再弹出 F,这时候
回到顶点 B,
同理规则 1 应用不了,应用规则 2,弹出 B,
这时候栈中只有顶点 A了,然后 A 还有未访问的邻接点,所有接下来访问顶点 C,
但是 C又是这条线的终点,所以从栈中弹出它,再次回到 A,
接着访问 D,G,I,
最后也回到了 A,然后访问 E,但是最后又回到了顶点 A,
这时候我们发现 A没有未访问的邻接点了,所以也把它弹出栈。
现在栈中已无顶点,于是应用规则 3,完成了整个搜索过程。

深度优先搜索在于能够找到与某一顶点邻接且没有访问过的顶点。

实现深度优先搜索的栈

package cn.learn.datastructure.graph;

/**
 * @author 阿康
 * 实现深度优先搜索的栈StackX
 */
public class StackX {

    /**
     * size 定义长度
     * st 栈实现数组
     * top 栈顶指针
     */
    final int size = 20;
    int[] st;
    int top;

    public StackX() {
        this.st = new int[size];
        top = -1;
    }

    public void push(int data){
        st[++top] = data;
    }

    public int pop() {
        return st[top--];
    }

    /**
     * 查看栈顶元素
     */
    public int peek() {
        return st[top];
    }

    public boolean isEmpty() {
        return top == -1;
    }

}

在图中实现深度优先搜索

Java代码实现(可运行) , 需要添加上StackX类

package com.example.demo.datastructure.graph;

/**
 * @author sk143
 * 封装图实现
 */
public class Graph {

    /**顶点个数*/
    final int MAX_VERT = 20;

    /**顶点数组*/
    private Vertex[] vertexList;

    /**邻接矩阵储存"边"数组元素0表示无边界,数组1表示有边界*/
    private int[][] adjMat;

    /**顶点个数*/
    private int nVert;

    /**使用栈实现深度优先搜索*/
    private Stack theStack;


    /**
     * 图结构初始化
     */
    public Graph() {
        // 定点列表
        vertexList = new Vertex[MAX_VERT];
        // 邻接矩阵
        adjMat = new int[MAX_VERT][MAX_VERT];
        // 顶点个数
        nVert = 0;
        // 初始化邻接矩阵元素都为 0,即所有定点都没边
        for (int i = 0; i < MAX_VERT; i++) {
            for (int j = 0; j < MAX_VERT; j++) {
                adjMat[i][j] = 0;
            }
        }
        theStack = new Stack();
        //theQueue = new Queue();
    }

    /**
     * 添加顶点到数组中
     */
    public void insert(char label) {
        vertexList[nVert++] = new Vertex(label);
    }

    /**
     * 邻接矩阵表示边是对称的,两部分都要赋值
     */
    public void addEdge(int start, int end) {
        adjMat[start][end] = 1;
        adjMat[end][start] = 1;
    }

    /**
     * 打印某个顶点的值
     */
    public void disPlayVertex(int v) {
        System.out.print(vertexList[v].label);
    }

    /**
     * 深度优先搜索法:
     * 1.用peek()方法检查栈顶的顶点
     * 2.用getAdjUnvisitedVertex()方法找到当前栈顶点邻接且未被访问的顶点
     * 3.第二部方法返回值不等于-1,则找到下一个未访问的邻接顶点,访问这个顶点,
     * 并入栈,返回-1则没有找到,出栈
     */
    public void depthFirstSearch() {
        // 从第一个顶点开始访问
        // 访问后标记未true
        vertexList[0].isVisited = true;
        // disPlayVertex(0);
        // 将第一个顶点放到栈中
        theStack.push(0);

        while (!theStack.isEmpty()) {
            // 找到未访问的邻接点
            int current = theStack.peek();
            int v = getAdjUnvisitedVertex(current);
            if (v == -1) {
                // 如果当前顶点为-1,表示没有邻接且未被访问出顶点
                theStack.pop();
            } else {
                vertexList[v].isVisited = true;
                disPlayVertex(current);
                disPlayVertex(v);
                System.out.println("  ");
                theStack.push(v);
            }
        }
        // 栈访问完毕,重置所有标记位置isVisited = false;
        for (int i = 0; i < nVert; i++) {
            vertexList[i].isVisited = false;
        }
    }

    /**
     * 找到与某一顶点邻接且未被访问的顶点
     */
    private int getAdjUnvisitedVertex(int v) {
        for (int i = 0; i < nVert; i++) {
            if (adjMat[v][i] == 1 && !vertexList[i].isVisited) {
                return i;
            }
        }
        return -1;
    }

    public static void main(String[] args) {
        Graph graph = new Graph();
        graph.insert('A');
        graph.insert('B');
        graph.insert('C');
        graph.insert('D');
        graph.insert('E');

        graph.addEdge(0, 1); // AB
        graph.addEdge(1, 2); // BC
        graph.addEdge(0, 3); // AD
        graph.addEdge(0, 4); // DE

        System.out.println();
        graph.depthFirstSearch();// ABCDE

        System.out.println("-----------");

    }
}

运行结果如下


AB  
BC  
AD  
AE  
-----------

(转载请标明出处)
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值