深度优先DFS与广度优先BFS

先简单记录基础逻辑。深度优先基于栈,广度优先基于队列。

使用的都是邻接矩阵而非邻接表。输出没有显示路径层次。


//深度优先DFS
class StackX {
    private int[] st;
    private final int size = 20;
    private int top;

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

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

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

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

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

// 顶点
class Vertex {
    char label;
    boolean visited;

    public Vertex(char label) {
        this.label = label;
        visited = false;
    }

}

public class Graph {
    private final int maxVer = 20;// 最大顶点数
    private int[][] adjMat;// 邻接矩阵
    private Vertex[] vertex;// 顶点数组
    private int curVer;// 当前顶点数
    private StackX stack;

    public Graph() {
        curVer = 0;
        stack = new StackX();
        vertex = new Vertex[maxVer];
        adjMat = new int[maxVer][maxVer];
        for (int i = 0; i < maxVer; i++)
            for (int j = 0; j < maxVer; j++)
                adjMat[i][j] = 0;
    }

    // 添加顶点
    public void addVer(char label) {
        vertex[curVer++] = new Vertex(label);
    }

    // 添加边
    public void addAdj(int i, int j) {
        if (i == j)// 自己与自己无边
            return;
        adjMat[i][j] = 1;
        adjMat[j][i] = 1;
    }

    public void displayVer(int index) {
        System.out.print(vertex[index].label);
    }

    public void dfs(int index) {
        vertex[index].visited = true;
        displayVer(index);
        stack.push(index);
        int k;
        while (!stack.isEmpty()) {
            k = findUnvisitedAdj(stack.peek());
            if (k == -1)
                stack.pop();
            else {
                stack.push(k);
                vertex[k].visited = true;
                displayVer(k);
            }
        }
        // 搜索一次后重置访问状态,便于下次搜索
        for (int i = 0; i < curVer; i++)
            vertex[i].visited = false;
    }

    // 找到一个未访问过的相邻顶点
    public int findUnvisitedAdj(int index) {
        for (int i = 0; i < curVer; i++)
            if (adjMat[index][i] == 1 && vertex[i].visited == false)
                return i;
        return -1;
    }
    public static void main(String[] args) {
        Graph g = new Graph();
        g.addVer('A');
        g.addVer('B');
        g.addVer('C');
        g.addVer('D');
        g.addVer('E');
        g.addVer('F');
        g.addAdj(0, 1);
        g.addAdj(1, 2);
        g.addAdj(2, 3);
        g.addAdj(3, 5);
        g.addAdj(0, 5);
        g.addAdj(1, 4);
        g.dfs(0);
    }

}

//BFS
class Que {
    static final int size = 20;
    private int[] array;
    private int front;
    private int rear;

    public Que() {
        array = new int[size];
        front = 0;
        rear = -1;
    }

    public void add(int key) {
        if (rear == size - 1)// 满了覆盖加入,满了是否禁止加好?
            rear = -1;
        array[++rear] = key;
    }

    public boolean isEmpty() {
        return (front + size - 1 == rear || rear + 1 == front);
      
    }

    public int removeFirst() {//此处不需判断是否为空,因为使用时判断不为空才remove的
        int temp = array[front++];
        if (front == size)
            front = 0;
        return temp;
    }
}

public class Graph2 {
    class Vertex2 {
        char label;
        boolean visited;

        public Vertex2(char label) {
            this.label = label;
            visited = false;
        }
    }

    private Vertex2[] vertex;
    // 小于队列size
    private int maxSize;
    private int curSize;
    private int[][] adjMat;
    private Que queue;

    public Graph2(int size) {
        queue = new Que();
        maxSize = size;
        vertex = new Vertex2[maxSize];
        curSize = 0;
        adjMat = new int[maxSize][maxSize];
        for (int i = 0; i < maxSize; i++)
            for (int j = 0; j < maxSize; j++)
                adjMat[i][j] = 0;
    }

    public void addVer(char label) {
        vertex[curSize++] = new Vertex2(label);
    }

    public void addAdj(int first, int end) {
        if (first == end)//不要也可以,自己肯定是visit过的
            return;
        adjMat[first][end] = 1;
        adjMat[end][first] = 1;
    }

    // 广度优先
    public void bfs(int index) {
        vertex[index].visited = true;
        display(index);
        queue.add(index);
        int key;
        while (!queue.isEmpty()) {
            int temp = queue.removeFirst();
            while ((key = findUnvisitedAdj(temp)) != -1) {
                vertex[key].visited = true;
                queue.add(key);
                display(key);
            }
        }
        // 重置
        for (int i = 0; i < curSize; i++)
            vertex[i].visited = false;

    }

    private int findUnvisitedAdj(int temp) {
        for (int i = 0; i < curSize; i++)
            if (adjMat[temp][i] == 1 && vertex[i].visited == false)
                return i;
        return -1;
    }

    private void display(int index) {
        System.out.print(vertex[index].label);
    }

    public static void main(String[] args) {
        Graph2 g2 = new Graph2(10);
        g2.addVer('A');
        g2.addVer('B');
        g2.addVer('C');
        g2.addVer('D');
        g2.addVer('E');
        g2.addVer('F');
        g2.addVer('G');
        g2.addVer('H');
        g2.addVer('I');
        g2.addAdj(0, 1);
        g2.addAdj(1, 4);
        g2.addAdj(1, 5);
        g2.addAdj(0, 2);
        g2.addAdj(2, 6);
        g2.addAdj(0, 3);
        g2.addAdj(3, 7);
        g2.addAdj(3, 8);
        g2.bfs(1);
    }
}
输出不太好看,没有路径层次信息。想写个搜索2个点之间所有路径的方法,在DFS里写不出来。。。感觉BFS应该好写些。



猜你喜欢

转载自blog.csdn.net/qq_26567507/article/details/80277386