圖的遍歷方式

圖的遍歷方式

圖的遍歷:從圖中某一頂點出發訪問圖中其餘頂點,且每一個頂點僅被訪問一次。

圖有2種常見的遍歷方式(有向圖、無向圖都適用)

  • 廣度優先搜索(Breadth First Search,BFS),又稱爲寬度優先搜索、橫向優先搜索
  • 深度優先搜索(Depth First Search,DFS)

廣度優先搜索

廣度優先搜索:從起始節點開始一層一層的進行遍歷,只有完全遍歷完一層所有的節點後纔會進入下一層的遍歷。二叉樹的層序遍歷就是一種廣度優先搜索。

在這裏插入圖片描述

在這裏插入圖片描述

Graph<V, E>接口中添加內部接口:

    interface Visitor<V> {
        boolean visit(V v);
    }

代碼實現如下:

    public void bfs(V begin, Visitor<V> visitor) {

        // 根據值獲取起始頂點
        Vertex<V, E> beginVertex = vertices.get(begin);

        if(Objects.isNull(beginVertex)) {
            return;
        }

        Queue<Vertex<V, E>> queue = new LinkedList<>();
        Set<Vertex<V, E>> visitedVertices  = new HashSet<>(); // 記錄已經添加入隊列中的頂點
        queue.offer(beginVertex);
        visitedVertices.add(beginVertex);

        while (!queue.isEmpty()) {
            Vertex<V, E> vertex = queue.poll();

            // 返回true終止遍歷
            if(visitor.visit(vertex.value)) {
                return;
            }

            vertex.outEdges.forEach(edge -> {
                if(!visitedVertices.contains(edge.toVertex)) {
                    queue.offer(edge.toVertex);
                    visitedVertices.add(edge.toVertex);
                }
            });
        }

    }

深度優先搜索

深度優先搜索:從起始節點沿着樹的深度遍歷樹的節點,儘可能深的搜索樹的分支。當節點v的所在邊都己被探尋過或者無法繼續往下搜索時,搜索將回溯到發現節點v的那條邊的起始節點,整個進程反覆進行直到所有節點都被訪問爲止。二叉樹的前序遍歷就是一種深度優先搜索。

在這裏插入圖片描述
在這裏插入圖片描述

遞歸實現

    public void dfs(V begin, Visitor<V> visitor) {

        // 根據值獲取起始頂點
        Vertex<V, E> beginVertex = vertices.get(begin);

        if(Objects.isNull(beginVertex)) {
            return;
        }

        // 遞歸調用
        dfs(beginVertex, visitor, new HashSet<>());
    }

    // dfs返回true,中斷遍歷
    private boolean dfs(Vertex<V, E> vertex, Visitor<V> visitor, Set<Vertex<V, E>> visitedVertices) {
        if(visitor.visit(vertex.value)) {
            return true;
        }
        visitedVertices.add(vertex);

        Iterator<Edge<V, E>> iterator = vertex.outEdges.iterator();
        while (iterator.hasNext()) {
            Edge<V, E> edge = iterator.next();
            if(!visitedVertices.contains(edge.toVertex)) {
                if(dfs(edge.toVertex, visitor, visitedVertices)) {
                    return true;
                }
            }
        }
        return false;
    }

迭代實現

    public void dfs(V begin, Visitor<V> visitor) {

        // 根據值獲取起始頂點
        Vertex<V, E> beginVertex = vertices.get(begin);

        if (Objects.isNull(beginVertex)) {
            return;
        }

        Set<Vertex<V, E>> visitedVertices = new HashSet<>();

        Stack<Vertex<V, E>> stack = new Stack<>();
        stack.push(beginVertex);
        visitedVertices.add(beginVertex);
        if(visitor.visit(beginVertex.value)) {
            return;
        }

        while (!stack.isEmpty()) {

            Vertex<V, E> vertex = stack.pop();

            Iterator<Edge<V, E>> iterator = vertex.outEdges.iterator();
            while (iterator.hasNext()) {
                Edge<V, E> edge = iterator.next();
                if(!visitedVertices.contains(edge.toVertex)) {
                    stack.push(vertex);
                    stack.push(edge.toVertex);
                    visitedVertices.add(edge.toVertex);
                    if(visitor.visit(edge.toVertex.value)) {
                        return;
                    }
                    break;
                }
            }
        }

    }

更多精彩內容關注本人公衆號:架構師升級之路
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章