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