图的两种存储结构 邻接矩阵和邻接表 java实现

本文介绍了邻接矩阵和邻接列表两种表示图的数据结构,包括它们的概念、表示方法、优缺点,以及对应的Java代码示例。重点强调了邻接矩阵适用于直观快速查询,但空间消耗大,而邻接列表更节省空间,适合稀疏图,但查询效率较低。
摘要由CSDN通过智能技术生成

邻接矩阵是一种表示图的数据结构,通过二维数组来表示图中的顶点和边的关系。在邻接矩阵中,行和列分别代表图中的顶点,而矩阵中的元素表示顶点之间是否有边,以及边的权重(在带权图中)。以下是邻接矩阵的基本概念和使用方法:

1. 基本概念:

  • 顶点(Vertex): 图中的节点。
  • 边(Edge): 顶点之间的连接线。
  • 有向图(Directed Graph): 边有方向的图。
  • 无向图(Undirected Graph): 边没有方向的图。
  • 邻接矩阵(Adjacency Matrix): 一个二维数组,用于表示图的结构。

2. 邻接矩阵的表示方法:

  • 图的大小: 如果图有 n 个顶点,那么邻接矩阵是一个 n x n 的二维数组。
  • 矩阵元素: 矩阵中的元素 matrix[i][j] 表示顶点 i 到顶点 j 是否有边。对于无权图,通常用 0 或 1 表示是否相邻;对于带权图,可以使用权重值表示。

3. 邻接矩阵的优点和缺点:

  • 优点:

    • 直观:易于理解和实现。
    • 查询两个顶点之间是否有边的操作很快速,只需查看数组中的一个元素。
  • 缺点:

    • 浪费空间:对于稀疏图(边相对较少),邻接矩阵会占用大量空间,因为大部分元素是 0。
    • 插入和删除边的操作较慢,因为需要修改矩阵。

代码如下:

public class Graph <T>{
    protected final int MAXSIZE=10;
    protected final int MAX=999;
    protected T[] V;
    protected int[][] arcs;
    protected int e;
    protected int n;

    public Graph(){
        V=(T[])new Object[MAXSIZE];
        arcs=new int[MAXSIZE][MAXSIZE];
    }

    public int LocateVex(T v){
        int i;
        for(i=0;i<n;i++){
            if(V[i]==v){
                return i;
            }
        }
        return -1;
    }

    public void DisplayAdjMatrix(){
        int i,j;
        System.out.println("The Adjacency Matrix is:");
        for(i=0;i<n;i++){
            for(j=0;j<n;j++){
                System.out.print(arcs[i][j]+" ");
            }
            System.out.println();
        }
    }

    public void CreateAdj() {
        int i, j, k;
        T v1, v2;
        Scanner sc = new Scanner(System.in);

        System.out.println("请输入图的顶点数和边数:");
        System.out.println("顶点数 n = ");
        n = sc.nextInt();

        System.out.println("边数 e = ");
        e = sc.nextInt();

        System.out.println("请输入图的顶点信息:");
        String str = sc.next();
        for (i = 0; i < n; i++) {
            V[i] = (T)(Object)str.charAt(i);
        }

        for (i = 0; i < n; i++) {
            for (j = 0; j < n; j++) {
                arcs[i][j] = 0;
            }
        }

        System.out.println("请输入图的边信息:");
        for (k = 0; k < e; k++) {
            System.out.println("请输入第" + (k + 1) + "条边的两个顶点:");
            v1 = (T)(Object)sc.next().charAt(0);
            v2 = (T)(Object)sc.next().charAt(0);
            i = LocateVex(v1);
            j = LocateVex(v2);
            if (i >= 0 && j >= 0) {
                arcs[i][j] = 1;
                arcs[j][i] = 1;//如果需要有向图,去掉这句
            } else {
                System.out.println("输入的顶点信息不合法,请重新输入。");
                k--; // 使得循环变量 k 不增加,重新输入当前边
            }
        }
    }


    public static void main(String[] args) {
        Graph<Character> g=new Graph<Character>();
        g.CreateAdj();
        g.DisplayAdjMatrix();
    }
}

邻接表是一种用链表来表示图的数据结构,每个顶点都关联一个链表,链表中存储与该顶点相邻的其他顶点。相比邻接矩阵,邻接表更适用于稀疏图(顶点较多,但边相对较少),因为它能够更有效地利用内存空间。以下是邻接表的基本概念和使用方法:

1. 基本概念:

  • 顶点(Vertex): 图中的节点。
  • 边(Edge): 顶点之间的连接线。
  • 邻接表(Adjacency List): 用链表来表示图中顶点和相邻顶点的关系。

2. 邻接表的表示方法:

  • 链表节点: 每个顶点都有一个关联的链表,链表中的节点表示与该顶点相邻的其他顶点。
  • 数组: 用数组来存储所有顶点的链表头。

3. 邻接表的优点和缺点:

  • 优点:

    • 节省空间:对于稀疏图,邻接表比邻接矩阵更节省内存,因为只存储存在的边。
    • 插入和删除边的操作较快,只需要对链表进行操作。
  • 缺点:

    • 查询两个顶点之间是否有边的操作可能较慢,需要遍历链表。

节点代码:

public class ArcNode {
    int adjVex;
    ArcNode nextArc;
    int weight;

    public ArcNode() {
        adjVex = 0;
        nextArc = null;
        weight = 0;
    }
}
public class VNode<T>{
    T data;
    ArcNode firstArc;

    public VNode(){
        data=null;
        firstArc=null;
    }
}

1. VNode 类:

VNode 类表示图中的顶点,每个顶点都关联一个邻接表。该类有两个主要成员变量:

  • data: 存储顶点的信息,可以是任意类型的数据。
  • firstArc: 是一个指向 ArcNode 类型的引用,指向该顶点的邻接表的第一个节点。

这个类定义了邻接表中顶点的结构,其中 data 存储顶点的值,而 firstArc 则指向与该顶点相邻的第一个节点,从而构成了链表。

2. ArcNode 类:

ArcNode 类表示邻接表中的链表节点,用于存储与某一顶点相邻的其他顶点的信息。该类有三个主要成员变量:

  • adjVex: 存储相邻顶点的位置或索引。
  • nextArc: 是一个指向 ArcNode 类型的引用,指向链表中的下一个节点。
  • weight: 存储边的权重(在这里未使用)。

这个类定义了邻接表中链表节点的结构,其中 adjVex 存储与当前顶点相邻的另一个顶点的位置,nextArc 则指向链表中下一个相邻节点,构成了链表结构。

图代码:

public class ALGraph<T>{
    protected final int MAXSIZE=10;
    protected VNode[] adjList;
    int n,e;
    public ALGraph(){
        adjList=new VNode[MAXSIZE];
    }

    public void CreateLink(){
        int i,j,k;
        T v1,v2;
        ArcNode s;
        String str;

        Scanner sc=new Scanner(System.in);

        System.out.println("请输入图的顶点数和边数:");
        System.out.println("顶点数 n = ");
        n=sc.nextInt();

        System.out.println("边数 e = ");
        e=sc.nextInt();

        System.out.println("请输入图的顶点信息:");
        str=sc.next();

        for(i=0;i<n;i++){
            adjList[i]=new VNode<T>();
            adjList[i].data=str.charAt(i);
            adjList[i].firstArc=null;
        }

        System.out.println("请输入图的边的信息:");
        for (k = 0; k < e; k++) {
            System.out.println("请输入第" + (k + 1) + "条边的两个顶点:");
            str = sc.next();
            v1 = (T) (Object) str.charAt(0);
            v2 = (T) (Object) str.charAt(1);
            i = LocateVex(v1);
            j = LocateVex(v2);

            if (i>=0 && j>=0) {
                s=new ArcNode();
                s.adjVex=j;
                s.nextArc=adjList[i].firstArc;
                adjList[i].firstArc=s;
                s=new ArcNode();//删除本行及下面部分得到有向图
                s.adjVex=i;
                s.nextArc=adjList[j].firstArc;
                adjList[j].firstArc=s;
            }

        }
    }

    public int LocateVex(T v){
        int i;
        for(i=0;i<n;i++){
            if(adjList[i].data==v){
                return i;
            }
        }
        return -1;
    }

    public void DisplayAdjList(){
        int i;
        ArcNode p;
        System.out.println("The Adjacency List is:");
        for(i=0;i<n;i++){
            System.out.print(adjList[i].data+"->");
            p=adjList[i].firstArc;
            while(p!=null){
                System.out.print(p.adjVex+" ");
                p=p.nextArc;
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        ALGraph<Character> g=new ALGraph<>();
        g.CreateLink();
        g.DisplayAdjList();
    }

}

  • 32
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值