JAVA數據結構----圖的存儲結構之鄰接表

數據結構系列是我學習做的筆記,會持續更新,源碼分享在github:數據結構,當然你也可以從下面的代碼片中獲取
注:github代碼更新會有延遲,關注不迷路😄

本篇博文簡單介紹鄰接表與其存儲圖的特點,並用java實現

1. 鄰接表

鄰接表(Adjacency list)是圖的一種鏈式存儲方法,其是由一個順序存儲的頂點表和n個鏈式存儲的邊表組成。其中,頂點表由定點節點組成,邊表是由邊(弧)節點組成的一個單鏈表,表示所有依附於頂點v_i的邊。

2. 具體實現代碼

2.1 圖的類型枚舉:GraphKind.java
package code.Graph;

/*
* 羅列圖的四種類型
* */
public enum GraphKind {
    UDG,        //無向圖----(UnDirected Graph)

    DG,         //有向圖----(Directed Graph)

    UDN,        //無向網----(UnDirected Network)

    DN;         //有向網----(Directed Network)

}
2.2 圖的接口:IGraph .java
package code.Graph;
/*
 * 圖的存儲結構除了存儲圖中各個頂點的信息外,還要存儲與頂點相關聯的邊的信息,
 * 圖的常見存儲結構有鄰接矩陣,鄰接表,鄰接多重表,十字鏈表
 *
 * 圖的接口
 *
 * */
public interface IGraph {

    /**創建一個圖*/
    public void createGraph();

    /**返回圖中的頂點數*/
    public int getVexNum();

    /**返回圖中的邊數*/
    public int getArcNum();

    /**
    * 給定點的位置v,返回其對應的頂點值,其中, 0 <=  v  < vexNum
     * @param v
    * */
    public Object getVex(int v) throws Exception;

    /**
    * 給定頂點的值vex,返回其在圖中的位置,如果圖中不包含此定點,返回-1
     * @param vex
    */
    public int locateVex(Object vex);

    /**
    * 返回v的第一個鄰接點,若V沒有鄰接點,則返回-1,其中, 0 <=  v  < vexNum
     * @param v
    */
    public int firstAdjVex(int v) throws Exception;

    /**
    * 返回v相對於w的下一個鄰接點,若w是v的最後一個鄰接點,則返回-1,其中, 0 <= v,  w  < vexNum
     * @param v
     * @param w
    */
    public int nextAdjVex(int v,int w) throws Exception;
}
2.3 頂點節點類:VNode.java
package code.Graph;
/**
 * 圖的鄰接表存儲表示中的頂點節點類
 * */
public class VNode {
    public Object data;//頂點信息
    public ArcNode firstArc;//指向第一條依附於該頂點的弧

    public VNode(Object data) {
        this(data,null);
    }

    public VNode(Object data, ArcNode firstArc) {
        this.data = data;
        this.firstArc = firstArc;
    }

    public VNode() {
        this(null,null);
    }

    public Object getData() {
        return data;
    }

    public ArcNode getFirstArc() {
        return firstArc;
    }
}
2.4 邊(或弧)節點類:ArcNode.java
package code.Graph;
/**
 * 圖的鄰接表存儲表示中的邊(或弧)節點類
 *
 * */
public class ArcNode {
    public int adjVex;//該弧所指向的頂點位置

    public int value;//邊或弧的權值

    private ArcNode nextArc;//指向下一條弧

    public ArcNode(int adjVex, int value, ArcNode nextArc) {
        this.adjVex = adjVex;
        this.value = value;
        this.nextArc = nextArc;
    }

    public ArcNode(int adjVex, int value) {
        this(adjVex,value,null);
    }

    public ArcNode(int adjVex) {
        this(adjVex,0,null);
    }

    public ArcNode() {
        this(-1,0,null);
    }

    public int getAdjVex() {
        return adjVex;
    }

    public int getValue() {
        return value;
    }

    public ArcNode getNextArc() {
        return nextArc;
    }

    public void setAdjVex(int adjVex) {
        this.adjVex = adjVex;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public void setNextArc(ArcNode nextArc) {
        this.nextArc = nextArc;
    }
}

2.5 圖的鄰接表類:ALGraph.java
package code.Graph;

import java.util.Scanner;

public class ALGraph implements IGraph{

    private GraphKind kind;//圖的種類標誌

    private int vexNum,arcNum;//圖的當前頂點數和邊數

    private VNode[] vexs;//頂點

    public ALGraph() {
        this(null,0,0,null);
    }

    public ALGraph(GraphKind kind, int vexNum, int arcNum, VNode[] vexs) {
        this.kind = kind;
        this.vexNum = vexNum;
        this.arcNum = arcNum;
        this.vexs = vexs;
    }

    /**
     * 創建一個圖
     */
    @Override
    public void createGraph() {
        Scanner sc = new Scanner(System.in);
        System.out.println("請輸入圖的類型:");
        GraphKind kind = GraphKind.valueOf(sc.next());
        switch (kind){
            case UDG:
                createUDG();
                return;
            case DG:
                createDG();
                return;
            case UDN:
                createUDN();
                return;
            case DN:
                createDN();
                return;
        }
    }

    //創建 圖,網 的工具方法
    private void createNetworkOrGraphUnit(){
        Scanner sc = new Scanner(System.in);
        System.out.println("請分別輸入圖的頂點數,圖的邊數");
        vexNum = sc.nextInt();//圖的頂點數
        arcNum = sc.nextInt();//圖的邊數

        vexs = new VNode[vexNum];//存儲頂點的數組

        System.out.println("請分別輸入圖的各個頂點:");
        for (int v = 0;v < vexNum;v++){//構造頂點向量
            vexs[v] = new VNode(sc.next());
        }

    }

    //有向圖
    private void createDG() {
        Scanner sc = new Scanner(System.in);
        createNetworkOrGraphUnit();
        System.out.println("請輸入各邊的頂點及其權值:");

        for (int k = 0;k < arcNum;k++){
            int v = locateVex(sc.next());//弧頭
            int u = locateVex(sc.next());//弧尾
            addArc(v,u,1);
        }

    }

    //無向圖
    private void createUDG() {
        Scanner sc = new Scanner(System.in);
        createNetworkOrGraphUnit();
        System.out.println("請輸入各邊的頂點:");

        for (int k = 0;k < arcNum;k++){
            int v = locateVex(sc.next());//弧頭
            int u = locateVex(sc.next());//弧尾
            int value = 1;
            addArc(v,u,value);
            addArc(u,v,value);
        }

    }

    //無向網
    private void createUDN(){
        Scanner sc = new Scanner(System.in);
        createNetworkOrGraphUnit();
        System.out.println("請輸入各邊的頂點及其權值:");

        for (int k = 0;k < arcNum;k++){
            int v = locateVex(sc.next());//弧頭
            int u = locateVex(sc.next());//弧尾
            int value = sc.nextInt();
            addArc(v,u,value);
            addArc(u,v,value);
        }
    }

    //有向網
    private void createDN(){
        Scanner sc = new Scanner(System.in);
        createNetworkOrGraphUnit();
        System.out.println("請輸入各邊的頂點及其權值:");

        for (int k = 0;k < arcNum;k++){
            int v = locateVex(sc.next());//弧頭
            int u = locateVex(sc.next());//弧尾
            int value = sc.nextInt();
            addArc(v,u,value);
        }

    }

    /**
     * 在位置爲v,u的頂點之間添加一條弧,其權值爲value
     * */
    public void addArc(int v,int u,int value){
        ArcNode arc = new ArcNode(u,value);
        arc.setNextArc(vexs[v].firstArc);
        vexs[v].firstArc = arc;
    }

    /**
     * 返回圖中的頂點數
     */
    @Override
    public int getVexNum() {
        return vexNum;
    }

    /**
     * 返回圖中的邊數
     */
    @Override
    public int getArcNum() {
        return arcNum;
    }

    /**
     * 給定點的位置v,返回其對應的頂點值,其中, 0 <=  v  < vexNum
     *
     * @param v
     */
    @Override
    public Object getVex(int v) throws Exception {
        if (v < 0 && v >= vexNum){
            throw new Exception("第" + v + "個頂點不存在!");
        }
        return vexs[v].getData();
    }

    /**
     * 給定頂點的值vex,返回其在圖中的位置,如果圖中不包含此定點,返回-1
     *
     * @param vex
     */
    @Override
    public int locateVex(Object vex) {
        for (int v = 0;v<vexNum;v++){
            if (vexs[v].data.equals(vex)){
                return v;
            }
        }

        return -1;
    }

    /**
     * 返回v的第一個鄰接點,若V沒有鄰接點,則返回-1,其中, 0 <=  v  < vexNum
     *
     * @param v
     */
    @Override
    public int firstAdjVex(int v) throws Exception {
        if (v < 0 && v >= vexNum){
            throw new Exception("第" + v + "個頂點不存在!");
        }
        VNode vex = vexs[v];
        if (vex.firstArc != null){
            return vex.firstArc.adjVex;
        }else {
            return -1;
        }
    }

    /**
     * 返回v相對於w的下一個鄰接點,若w是v的最後一個鄰接點,則返回-1,其中, 0 <= v,  w  < vexNum
     *
     * @param v
     * @param w
     */
    @Override
    public int nextAdjVex(int v, int w) throws Exception {
        if (v < 0 && v >= vexNum){
            throw new Exception("第" + v + "個頂點不存在!");
        }
        VNode vex = vexs[v];
        ArcNode arcvw = null;
        for (ArcNode arc = vex.firstArc;arc != null;arc = arc.getNextArc()){
            if (arc.adjVex == w){
                arcvw = arc;
                break;
            }
        }
        if (arcvw != null && arcvw.getNextArc() != null){
            return arcvw.getNextArc().adjVex;
        }else {
                return -1;
            }

    }

    public GraphKind getKind() {
        return kind;
    }

    public VNode[] getVexs() {
        return vexs;
    }
}

有關圖的鄰接矩陣實現見此鏈接

發佈了27 篇原創文章 · 獲贊 49 · 訪問量 2264
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章