JAVA实现图的深度优先搜索和广度优先搜索

来源:互联网 发布:天气预报哪个软件好 编辑:程序博客网 时间:2024/05/21 11:12

1、深度优先搜索介绍

图的深度优先搜索(Depth First Search),和树的先序遍历比较类似。

它的思想:假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发,首先访问该顶点,然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和v有路径相通的顶点都被访问到。 若此时尚有其他顶点未被访问到,则另选一个未被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。

显然,深度优先搜索是一个递归的过程。

2、广度优先搜索介绍

广度优先搜索算法(Breadth First Search),又称为"宽度优先搜索"或"横向优先搜索",简称BFS。

它的思想是:从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使得“先被访问的顶点的邻接点先于后被访问的顶点的邻接点被访问,直至图中所有已被访问的顶点的邻接点都被访问到。如果此时图中尚有顶点未被访问,则需要另选一个未曾被访问过的顶点作为新的起始点,重复上述过程,直至图中所有顶点都被访问到为止。

换句话说,广度优先搜索遍历图的过程是以v为起点,由近至远,依次访问和v有路径相通且路径长度为1,2...的顶点。

3、代码实现



深度优先搜索需要用到Stack

广度优先搜索需要用到Queue


顶点类:

public class Vertex {    public char label;    // 标识是否已经被访问过了    public boolean isVisit;    public Vertex(char label, boolean isVisit) {        this.label = label;        this.isVisit = isVisit;    }}

图类:

public class Graph {    // 顶点的数组    private Vertex[] vertexList;    // 邻接矩阵    private int[][] adjMat;    // 数组最大大小    private int maxSize;    // 当前数组大小    private int nVertex;    /**     * 初始化顶点数组、邻接矩阵     */    public Graph(int maxSize) {        this.maxSize = maxSize;        vertexList = new Vertex[maxSize];        adjMat = new int[maxSize][maxSize];        for (int i = 0; i < maxSize; i++) {            for (int j = 0; j < maxSize; j++) {                adjMat[i][j] = 0;            }        }        nVertex = 0;    }    /**     * 添加顶点     */    public void addVertex(char label) {        vertexList[nVertex++] = new Vertex(label, false);    }    /**     * 添加边     */    public void addEdge(int start, int end) {        adjMat[start][end] = 1;        adjMat[end][start] = 1;    }    /**     * 深度优先搜索     */    public void dfs() {        // 从0号顶点开始        int v = 0;        String result = vertexList[v].label + " ";        vertexList[v].isVisit = true;        MyStack stack = new MyStack();        stack.push(v);        while (!stack.isEmpty()) {            v = stack.peek();            // 得到未访问过的邻接点            int unvisitedVertex = getUnvisitedVertex(v);            if(unvisitedVertex == -1) {                stack.pop();            } else{                result += vertexList[unvisitedVertex].label + " ";                vertexList[unvisitedVertex].isVisit = true;                stack.push(unvisitedVertex);            }        }        System.out.println(result);        // 将访问信息重置        resetVisit();    }    /**     * 广度优先搜索     */    public void bfs() {        // 从0号顶点开始        int v = 0;        vertexList[v].isVisit = true;        String result = vertexList[v].label + " ";        MyQueue queue = new MyQueue(100);        queue.insert(v);        while (!queue.isEmpty()) {            v = queue.peek();            // 得到未访问过的邻接点            int unvisitedVertex = getUnvisitedVertex(v);            if(unvisitedVertex == -1) {                queue.remove();            } else {                vertexList[unvisitedVertex].isVisit = true;                result += vertexList[unvisitedVertex].label + " ";                queue.insert(unvisitedVertex);            }        }        System.out.println(result);        // 将访问信息重置        resetVisit();    }    /**     * 获取未访问过的邻接点     */    public int getUnvisitedVertex(int v) {        for (int i = 0; i < nVertex; i++) {            if(adjMat[v][i] == 1 && vertexList[i].isVisit == false) {                return i;            }        }        return -1;    }    /**     * 将访问信息的属性重置     */    private void resetVisit() {        for (int i = 0; i < vertexList.length; i++) {            vertexList[i].isVisit = false;        }    }    /**     * 打印图矩阵     */    public void printGraph() {        System.out.println("********************************************");        System.out.print("\\ \t");        for (int i = 0; i < maxSize; i++) {            System.out.print(vertexList[i].label + "\t");        }        System.out.println();        for (int i = 0; i < maxSize; i++) {            System.out.print(vertexList[i].label + "\t");            for (int j = 0; j < maxSize; j++) {                System.out.print(adjMat[i][j] + "\t");            }            System.out.println();        }        System.out.println("********************************************");    }}
测试类:

public class Test {    public static void main(String[] args) {        Graph graph = new Graph(10);        graph.addVertex('A');        graph.addVertex('B');        graph.addVertex('C');        graph.addVertex('D');        graph.addVertex('E');        graph.addVertex('F');        graph.addVertex('G');        graph.addVertex('H');        graph.addVertex('I');        graph.addVertex('J');        graph.addEdge(0,1);        graph.addEdge(1,2);        graph.addEdge(2,3);        graph.addEdge(0,4);        graph.addEdge(4,5);        graph.addEdge(5,6);        graph.addEdge(0,7);        graph.addEdge(7,8);        graph.addEdge(8,9);        graph.printGraph();        graph.dfs();        graph.bfs();    }}

Stack类:

public class MyStack {//底层实现是一个数组private int[] arr;private int top;/** * 默认的构造方法 */public MyStack() {arr = new int[10];top = -1;}/** * 带参数构造方法,参数为数组初始化大小 */public MyStack(int maxsize) {arr = new int[maxsize];top = -1;}/** * 添加数据 */public void push(int value) {arr[++top] = value;}/** * 移除数据 */public int pop() {return arr[top--];}/** * 查看数据 */public int peek() {return arr[top];}/** * 判断是否为空 */public boolean isEmpty() {return top == -1;}/** * 判断是否满了 */public boolean isFull() {return top == arr.length - 1;}}

Queue类:

public class MyQueue {//底层使用数组private int[] arr;//有效数据的大小private int elements;//队头private int front;//队尾private int end;/** * 默认构造方法 */public MyQueue() {arr = new int[10];elements = 0;front = 0;end = -1;}/** * 带参数的构造方法,参数为数组的大小 */public MyQueue(int maxsize) {arr = new int[maxsize];elements = 0;front = 0;end = -1;}/** * 添加数据,从队尾插入 */public void insert(int value) {arr[++end] = value;elements++;}/** * 删除数据,从队头删除 */public int remove() {elements--;return arr[front++];}/** * 查看数据,从队头查看 */public int peek() {return arr[front];}/** * 判断是否为空 */public boolean isEmpty() {return elements == 0;}/** * 判断是否满了 */public boolean isFull() {return elements == arr.length;}}


阅读全文
0 1
原创粉丝点击