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


图的实现方式主要用到矩阵或链表,这里用的矩阵;

图的深度优先搜索就是一条路径一条路径的往完了走,需要用到栈;而广度优先搜索就是一层一层的搜索,需要用到队列;

这个是两种遍历方式都会用到的表示图节点的代码:

/**
 * @ClassName Node
 * @Description 图节点
 * @Author lzq
 * @Date 2019/6/19 04:39
 * @Version 1.0
 **/
public class Node {
    public char label;  //存放的数据
    public boolean wasVisited;  //记录有无被访问过

    public Node(char label) {
        this.label = label;
        this.wasVisited = false;
    }
}

图的深度优先搜索

代码:

import java.util.Stack;

/**
 * @ClassName Graph
 * @Description 图的深度优先搜索
 * @Author lzq
 * @Date 2019/6/19 04:41
 * @Version 1.0
 **/
public class Graph {
    private final int MAX_VERTS = 20;  //表示一个图节点能连接的最大定点数
    private Node[] nodeList;  //顶点数组
    private int[][] adjMat; //邻接矩阵,用来存方节点之间关系的
    private int nNode;  //当前顶点数量
    private Stack<Integer> stack;  //深度优先遍历需要用到

    public Graph() {
        nodeList = new Node[MAX_VERTS];
        adjMat = new int[MAX_VERTS][MAX_VERTS];
        nNode = 0;
        for (int i = 0; i < MAX_VERTS; i++) {
            for (int j = 0; j < MAX_VERTS; j++) {
                adjMat[i][j] = 0;
            }
        }
        stack = new Stack<>();
    }

    /**
     * 添加节点
     * @param lab
     */
    public void addNode(char lab) {
        nodeList[nNode++] = new Node(lab);
    }

    /**
     * 添加节点直接的边
     * @param start
     * @param end
     */
    public void addEdge(int start,int end) {
        adjMat[start][end] = 1;
        adjMat[end][start] = 1;
    }

    /**
     * 打印节点
     * @param v
     */
    private void dispalyNode(int v) {
        System.out.print(nodeList[v].label+"\t");
    }

    /**
     * 深度优先搜索
     */
    public void dfs() {
        nodeList[0].wasVisited = true;  //修改访问标志为访问过的
        dispalyNode(0);
        stack.push(0);  //存放的是节点的位置

        while (!stack.isEmpty()) {
            int v = getAdjUnvisitedVertex(stack.peek());
            if(v == -1) {
                stack.pop();  //没有未被访问的相邻节点,就是找完了
            }else {
                nodeList[v].wasVisited = true;
                dispalyNode(v);
                stack.push(v);
            }
        }

        //到这所有的节点都访问玩了,需要把访问状态改回去
        for (int i = 0; i < nNode; i++) {
            nodeList[i].wasVisited = false;
        }
    }

    /**
     * 获取指定顶点相邻接的未被访问节点
     * @param v
     * @return
     */
    private int getAdjUnvisitedVertex(int v) {
        for (int i = 0; i < nNode; i++) {
            if(adjMat[v][i] == 1 && !nodeList[i].wasVisited) {  //代表两个顶点之间是联通的,并且这个顶点没有被访问过
                return i;
            }
        }
        return -1;  //没有找到
    }
}

测试代码:

   public static void main(String[] args) {
        Graph graph = new Graph();
        graph.addNode('A');
        graph.addNode('B');
        graph.addNode('C');
        graph.addNode('D');
        graph.addEdge(0,1);
        graph.addEdge(0,2);
        graph.addEdge(0,3);
        graph.addEdge(1,3);
        graph.dfs();
    }

表示这个图:
在这里插入图片描述
运行结果:

在这里插入图片描述

图的广度优先搜索

import java.util.LinkedList;
import java.util.Queue;

/**
 * @ClassName Graph1
 * @Description 图的广度优先搜索
 * @Author lzq
 * @Date 2019/6/19 05:27
 * @Version 1.0
 **/
public class Graph1 {
    private final int MAX_VERTS = 20;  //表示一个图节点能连接的最大定点数
    private Node[] nodeList;  //顶点数组
    private int[][] adjMat; //邻接矩阵,用来存方节点之间关系的
    private int nNode;  //当前顶点数量
    private Queue<Integer> queue;  //广度优先搜索用到的队列

    public Graph1() {
        nodeList = new Node[MAX_VERTS];
        adjMat = new int[MAX_VERTS][MAX_VERTS];
        nNode = 0;
        for (int i = 0; i < MAX_VERTS; i++) {
            for (int j = 0; j < MAX_VERTS; j++) {
                adjMat[i][j] = 0;
            }
        }
        queue = new LinkedList<>();
    }

    /**
     * 添加节点
     * @param lab
     */
    public void addNode(char lab) {
        nodeList[nNode++] = new Node(lab);
    }

    /**
     * 添加节点直接的边
     * @param start
     * @param end
     */
    public void addEdge(int start,int end) {
        adjMat[start][end] = 1;
        adjMat[end][start] = 1;
    }

    /**
     * 打印节点
     * @param v
     */
    private void dispalyNode(int v) {
        System.out.print(nodeList[v].label+"\t");
    }

    /**
     * 广度优先搜索
     */
    public void bfs() {
        nodeList[0].wasVisited = true;  //修改访问标志为访问过的
        dispalyNode(0);
        queue.add(0);  //存放的是节点的位置
        int v2;

        while (!queue.isEmpty()) {
            int v1 = queue.remove();  //从队头取出一个顶点
            while ((v2 = getAdjUnvisitedVertex(v1)) != -1) {
                nodeList[v2].wasVisited = true;
                dispalyNode(v2);
                queue.add(v2);
            }

        }

        //到这所有的节点都访问玩了,需要把访问状态改回去
        for (int i = 0; i < nNode; i++) {
            nodeList[i].wasVisited = false;
        }
    }

    /**
     * 获取指定顶点相邻接的未被访问节点
     * @param v
     * @return
     */
    private int getAdjUnvisitedVertex(int v) {
        for (int i = 0; i < nNode; i++) {
            if(adjMat[v][i] == 1 && !nodeList[i].wasVisited) {  //代表两个顶点之间是联通的,并且这个顶点没有被访问过
                return i;
            }
        }
        return -1;  //没有找到
    }
}

测试:

 public static void main(String[] args) {
        Graph1 graph = new Graph1();
        graph.addNode('A');
        graph.addNode('B');
        graph.addNode('C');
        graph.addNode('D');
        graph.addNode('E');
        graph.addEdge(0,1);
        graph.addEdge(0,2);
        graph.addEdge(0,3);
        graph.addEdge(1,3);
        graph.addEdge(3,4);
        graph.bfs();
    }

在这里插入图片描述

发布了190 篇原创文章 · 获赞 189 · 访问量 15万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 创作都市 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览