java中圖的構造與遍歷

1、圖的定義。

圖分爲兩個部分組長,包括邊和點。將點用邊連接起來就形成了圖。
圖也分爲有向圖與無向圖。有向圖就是邊會帶上方向。指明從哪個點到哪個點,反之無向圖指沒有方向得邊。更多的時候會給邊加上值,在圖中,我們稱之爲該邊得權。有向圖中,叫做,有向帶權圖。無向圖中,叫做,無向帶權圖。

2、圖的構造

圖是由邊和點組成。那麼構造就從邊和點開始。
邊:
每條邊得兩端各對應一個點,邊得大小。所以圖得邊構造類如下:

 /**
     * 圖中的邊
     */

    //邊的左節點
    GraphNode leftNode;

    //邊的右節點
    GraphNode rightNode;

    //邊的權值
    int value;

    public GraphEdge(GraphNode leftNode,GraphNode rightNode,int value){
        this.leftNode = leftNode;
        this.rightNode = rightNode;
        this.value = value;
    }

點:

一個點可對應零條或者多條邊。以及爲了圖得遍歷,可對點設置boolean值。用來判斷該點是否遍歷過。點得構造類如下:

/**
     * 圖的節點
     */
     int value;//節點得值
     boolean tf;//節點是否遍歷過

     List<GraphEdge> edges;//該節點連接得邊


     public GraphNode(int value,boolean tf){
         this.value = value;
         this.tf = tf;
     }

     public void addEdge(GraphEdge edge){
         if(edges == null){
             edges= new ArrayList<>();
         }
         edges.add(edge);
     }

3、圖的遍歷

遍歷之前,先構造一個簡單得圖。構造代碼如下:

	/**
     * 生成圖
     */
    
    //存放點得集合
    List<GraphNode> nodeList = null;
    //初始化點
    public void initNode(int n ){
        if(nodeList == null){
            nodeList = new ArrayList<>();
        }

        GraphNode node = null;
        for(int i = 0; i < n ; i++){
            node = new GraphNode(i,false);
            nodeList.add(node);
        }
    }

    //初始化邊
    public void initGraph(int n){
        initNode(n);
        GraphEdge edge01 = new GraphEdge(nodeList.get(0),nodeList.get(1),0);
        GraphEdge edge02 = new GraphEdge(nodeList.get(0),nodeList.get(2),0);
        GraphEdge edge13 = new GraphEdge(nodeList.get(1),nodeList.get(3),0);
        GraphEdge edge14 = new GraphEdge(nodeList.get(1),nodeList.get(4),0);
        GraphEdge edge25 = new GraphEdge(nodeList.get(2),nodeList.get(5),0);
        GraphEdge edge26 = new GraphEdge(nodeList.get(2),nodeList.get(6),0);
        GraphEdge edge37 = new GraphEdge(nodeList.get(3),nodeList.get(7),0);
        GraphEdge edge47 = new GraphEdge(nodeList.get(4),nodeList.get(7),0);
        GraphEdge edge56 = new GraphEdge(nodeList.get(5),nodeList.get(6),0);
        GraphEdge edge67 = new GraphEdge(nodeList.get(6),nodeList.get(7),0);

        nodeList.get(0).addEdge(edge01);
        nodeList.get(0).addEdge(edge02);
        nodeList.get(1).addEdge(edge13);
        nodeList.get(1).addEdge(edge14);
        nodeList.get(2).addEdge(edge25);
        nodeList.get(2).addEdge(edge26);
        nodeList.get(3).addEdge(edge37);
        nodeList.get(4).addEdge(edge47);
        nodeList.get(5).addEdge(edge56);
        nodeList.get(6).addEdge(edge67);

    }
    //獲取所有點    
    public List<GraphNode> getNodeList() {
        return nodeList;
    }

構造完成之後進行圖的遍歷,可通過深度遍歷與廣度遍歷完成
深度遍歷可通過遞歸或棧完成。廣度遍歷可通過隊列完成。
1、圖得深度遍歷-棧

 public void dfSearchTraversing(GraphNode node) {
        if (node == null) {
            return;
        }
        Stack<GraphNode> stack = new Stack<GraphNode>();//創建棧
        stack.push(node);//加入首節點
        while (!stack.isEmpty()) {
            GraphNode node1 = stack.pop();//彈出首節點
            node1.setTf(true);//設置標記,該節點已訪問
            System.out.println("節點得值" + node1.getValue());
            List<GraphEdge> list = node1.getEdges();//根據節點獲得關聯得邊
            if (list == null) {//該點無對應得邊了
                continue;
            }
            for (int i = 0; i < list.size(); i++) {
                GraphEdge graphEdge = list.get(i);//獲取每條邊對應得另一端節點
                GraphNode temp = graphEdge.getRightNode();
                if (temp.getTf()) {//已訪問過,就跳過該節點。
                    continue;
                }
                stack.push(temp);//將沒訪問過得節點加入棧中
            }
        }

    }

2、圖得深度遍歷-遞歸
對遞歸算法不太瞭解得可參考上篇博客博客地址

 public void dfSearchTraversing(GraphNode node) {
        if (node == null || node.getTf()) { //判斷節點是否爲空,或者是否已經遍歷過
            return;
        }
        node.setTf(true);//設置已遍歷
        System.out.println("節點:"+node.getValue());
        List<GraphEdge> graphEdgeList = node.getEdges();//獲取左節點的應得邊
        if(graphEdgeList == null){
            return;
        }
        for(int i = 0; i < graphEdgeList.size(); i ++){
            GraphNode graphNode = graphEdgeList.get(i).getRightNode();//獲取邊得右節點
            if(graphNode.getTf()) {//判斷是否已經遍歷過
                continue;
            }
            dfSearchTraversing(graphNode);//遞歸調用
        }

    }

3、圖得廣度遍歷-隊列

public void bfSearchTraversing(GraphNode node) {
        if(node == null){
            return;
        }
        Queue<GraphNode> queue = new LinkedList<>();//創建隊列
        queue.add(node);//加入第一個節點
        while(queue.isEmpty() == false){
            GraphNode node1 = queue.remove();//先進先出。移除節點
            node1.setTf(true);//設置該節點已遍歷過
            System.out.println("值:"+node1.getValue());
            List<GraphEdge> list = node1.getEdges();//獲取點相關聯得邊
            if(list == null){
                continue;
            }
            for(int i = 0; i <list.size(); i++){
                GraphEdge graphEdge = list.get(i);//獲取邊對應得右節點
                GraphNode temp = graphEdge.getRightNode();
                if(temp.getTf()){//判斷該節點是否已經遍歷過
                    continue;
                }
                queue.add(temp);//加入到隊列中
            }
        }
    }

個人記錄,僅供參考。

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