图之深度优先生成森林

来源:互联网 发布:小光头脸型数据 编辑:程序博客网 时间:2024/04/28 20:52

生成森林是指由非连通图的连通分量的生成树所组成的森林,而深度优先生成森林则指由图的深度优先遍历算法获得的生成森林。

下面给出非连通图的深度优先生成森林算法的Java实现,其中生成森林采用孩子兄弟链表存储结构。

1. 深度优先生成森林算法实现

package org.sky.graph;import java.util.Scanner;public class DeepFirstSearchForest {    //表结点,包含边的相关信息    @SuppressWarnings("unused")    private static class ArcNode{        int adjVex;         //该弧或边所指向的顶点的位置        int value;          //与弧或边相关的信息,如权值        ArcNode nextArc;    //指向下一条弧或边的指针        public ArcNode(int adjVex, int value) {            super();            this.adjVex = adjVex;            this.value = value;        }        ArcNode(int adjvex, int value, ArcNode nextArc) {            super();            this.adjVex = adjvex;            this.value = value;            this.nextArc = nextArc;        }           public int getAdjVex() {            return adjVex;        }        public void setAdjVex(int adjVex) {            this.adjVex = adjVex;        }        public int getValue() {            return value;        }        public void setValue(int value) {            this.value = value;        }        public ArcNode getNextArc() {            return nextArc;        }        public void setNextArc(ArcNode nextArc) {            this.nextArc = nextArc;        }    }    //头结点,对应图中的顶点    @SuppressWarnings("unused")    private static class VNode{        Object data;        //顶点信息        ArcNode firstArc;   //指向第一条依附该顶点的弧或边的指针        public VNode(Object data) {            super();            this.data = data;        }        public VNode(Object data, ArcNode firstArc) {            super();            this.data = data;            this.firstArc = firstArc;        }        public Object getData() {            return data;        }        public void setData(Object data) {            this.data = data;        }        public ArcNode getFirstArc() {            return firstArc;        }        public void setFirstArc(ArcNode firstArc) {            this.firstArc = firstArc;        }           }    private int numVex;     //图的当前顶点数    private int numArc;     //图的当前边数或弧数    private VNode[] vexs;   //存储表头结点,通常采用顺序存储结构    public DeepFirstSearchForest() {        super();    }    public DeepFirstSearchForest(int numVex, int numArc, VNode[] vexs) {        super();        this.numVex = numVex;        this.numArc = numArc;        this.vexs = vexs;    }    /**     * @Desciption 创建有向网     */    public void createDN(){        Scanner sc = new Scanner(System.in);        System.out.println("请分别输入图的顶点数及边数");        numVex = sc.nextInt();        numArc = sc.nextInt();        vexs = new VNode[numVex];        System.out.println("请分别输入图的各个顶点:");        for(int v = 0; v < numVex; v++){            vexs[v] = new VNode(sc.next());        }        System.out.println("请输入各个边的来给你个顶点及其权值");        for(int k = 0; k < numArc; k++){            int v = locateVex(sc.next());            int u = locateVex(sc.next());            int value = sc.nextInt();            addArc(v,u,value);        }        sc.close();         }    /**     * @Desciption 创建无向网     */    public void createUDN(){        Scanner sc = new Scanner(System.in);        System.out.println("请分别输入图的顶点数及边数");        numVex = sc.nextInt();        numArc = sc.nextInt();        vexs = new VNode[numVex];        visited = new boolean[numVex];        System.out.println("请分别输入图的各个顶点:");        for(int v = 0; v < numVex; v++){            vexs[v] = new VNode(sc.next());            visited[v] = false;        }        System.out.println("请输入各个边的来给你个顶点及其权值");        for(int k = 0; k < numArc; k++){            int v = locateVex(sc.next());            int u = locateVex(sc.next());            int value = sc.nextInt();            addArc(v,u,value);            addArc(u,v,value);        }        sc.close();         }    /**     * @Desciption 返回与传入值相对应的定点位置     */     public int locateVex(Object vex){        for(int v = 0; v < numVex; v++){            if(vexs[v].getData().equals(vex)){                return v;            }        }        return -1;    }    /**     * @Desciption 在位置v和u间添加边,并赋权值     */    private void addArc(int v, int u, int value){        ArcNode arc = new ArcNode(u,value);        arc.setNextArc(vexs[v].getFirstArc());        vexs[v].setFirstArc(arc);    }///////////////////////////////////////深度优先生成森林(以孩子兄弟链表作生成森林的存储结构)//////////////////////////////////////////////    //孩子兄弟链表内部类    public class CSNode{        Object data;        CSNode firstChild;        CSNode nextSibling;        public CSNode(Object data, CSNode firstChild, CSNode nextSibling) {            super();            this.data = data;            this.firstChild = firstChild;            this.nextSibling = nextSibling;        }        public Object getData() {            return data;        }        public void setData(Object data) {            this.data = data;        }        public CSNode getFirstChild() {            return firstChild;        }        public void setFirstChild(CSNode firstChild) {            this.firstChild = firstChild;        }        public CSNode getNextSibling() {            return nextSibling;        }        public void setNextSibling(CSNode nextSibling) {            this.nextSibling = nextSibling;        }           }    private boolean[] visited;      //访问标志数组    private CSNode T = null;        //孩子兄弟链表        /**     * 深度优先遍历建立无向图的深度优先生成森林     */    public void DFSTraverse(){        CSNode q = null;        //指向当前生成树的根        for(int v = 0; v < numVex; v++){                if(!visited[v]){                CSNode p = new CSNode(vexs[v].getData(), null, null);                if(T == null){                    T = p;  //第一棵生成树的根                }else{                    q.setNextSibling(p);    //其他生成树的根                }                q = p;      //指向当前生成树的根                DFSTree(vexs, v, p);    //对尚未访问的顶点调用DFS            }        }    }    /**     * 从第v个顶点出发递归地深度优先遍历图     * @param vexs     * @param v     */    public void DFSTree(VNode[] vexs, int v, CSNode T){             visited[v] = true;        System.out.println(vexs[v].getData());   //输出访问的结点        boolean first = true;        CSNode q = null;        //指向当前生成树的根        for(int w = getFirstAdjVex(v); w >= 0; w = getNextAdjVex(v , w)){            if(!visited[w]){                CSNode p = new CSNode(vexs[w].getData(), null, null);                if(first){              //w是v的第一个未被访问的邻接顶点                    T.setFirstChild(p); //根的左孩子结点                    first = false;                }else{                  //w是v的其他未被访问的邻接顶点                    q.setNextSibling(p);//上一个邻接顶点的右兄弟结点                }                q = p;                DFSTree(vexs, w, q);    //对尚未访问的顶点调用DFS            }        }    }    /**     * 获取vexs[v]的第一个邻接弧的顶点位置     * @param vexs     * @param v     * @return vexs[v]的第一个邻接弧的顶点位置;若不存在,则返回-1     */    public int getFirstAdjVex(int v){        if(vexs[v].firstArc != null){ //第一个邻接弧是否存在            return vexs[v].firstArc.adjVex;        }        return -1;    }    /**     * 获取vexs[v]的相对第一个邻接弧的下一个邻接弧的顶点位置     * @param v     * @param w     * @return vexs[v]的相对第一个邻接弧的下一个邻接弧的顶点位置;若不存在,则返回-1     */    public int getNextAdjVex(int v, int w){        ArcNode temp =  vexs[v].firstArc;        int tempTail = -1;        while(temp != null){            if(temp.adjVex == w){                temp = temp.nextArc;                if(temp != null){                    tempTail = temp.adjVex;                    break;                }                           }else{                temp = temp.nextArc;            }        }               return tempTail;    }}

2. 测试代码

package org.sky.graph;public class TestGragh {    public static void main(String[] args){        DeepFirstSearchForest dfsForest = new DeepFirstSearchForest();        dfsForest.createUDN();        dfsForest.DFSTraverse();    }}
0 0