图表示法

一、相邻矩阵法

对于图形G=(V,E),假设有n个顶点,则可以将n个顶点的图形利用一个n*n二维矩阵表示,假如A(i,j)=1,则表示图形中有一条边(Vi,Vj)存在,否则A(i,j)=0,表示Vi到Vj之间不存在边。

  • 对无向图形,相邻矩阵一定是对称的,对角线为0。
  • 在无向图形中,任意节点i的度是矩阵第i行所有元素的和;在有向图中,节点i的出度是第i行所有元素的和,入度是第j列所有元素的和。
  • 用相邻矩阵法表示图形共需要n*n空间,无向图具有对称关系,仅需存储上三角或下三角,因此仅需n(n-1)/2空间。

我们以下图为例,用相邻矩阵进行存储。(有向图和无向图思路相同,只是矩阵不一定对称)

这里写图片描述

代码实现如下:

public class Test {
    public static void main(String[] args) {
        int[][] data= {{1,2},{1,5},{2,1},{2,3},{2,4},{3,2},{3,4},{3,5},{4,2},{4,3},{4,5},{5,1},{5,3},{5,4}};
        int[][] array=new int[6][6];     //矩阵大小为图顶点个数+1,下标0的位置不存数据
        int tempi,tempj;

        //核心代码
        for(int i=0;i<data.length;i++) {
            tempi=data[i][0];            //起始顶点
            tempj=data[i][1];            //终止顶点
            array[tempi][tempj]=1;       //有边的点填入1
        }

        System.out.println("无向图形矩阵:");
        for(int i=1;i<array.length;i++) {
            for(int j=1;j<array.length;j++) {
                System.out.print(array[i][j]+" ");
            }
            System.out.println();
        }
    }
}

程序运行结果如下:
这里写图片描述

优点:

  • 实现简单
  • 计算度相当方便
  • 要在图形中加入新边时,插入和删除简单

缺点:

  • 顶点与顶点之间路径不多时,易造成稀疏矩阵浪费空间
  • 计算所有顶点的分支度时,其时间复杂度为O(n2)

二、相邻表法

每个顶点使用一个链表,与该顶点相邻的节点存入该节点的链表中,即相当于把相邻矩阵中1的部分放入链表,忽略掉值为0的部分,可以避免浪费存储空间。
在无向图中,n个顶点e个边共需n个表头节点及2*e个节点,有向图中,链表只存放出度节点,因此需要n个表头节点及e个节点。

我们以上图为例,该图用相邻表法表示如下:
这里写图片描述

代码实现思路:我们先声明GraphLink类即链表类,该类中包括节点打印节点插入等函数。在主函数中声明存放链表的数组,大小为顶点个数,对每个顶点进行遍历,寻找与该顶点相邻的顶点存入链表中,该顶点处理完后打印链表。

具体代码如下:

public class Test {
    public static void main(String[] args) {
        int[][] data= {{1,2},{1,5},{2,1},{2,3},{2,4},{3,2},{3,4},{3,5},{4,2},{4,3},{4,5},{5,1},{5,3},{5,4}};
        System.out.println("图形的邻接表内容为:");
        GraphLink[] head=new GraphLink[6];       //声明一个存放链接表的数组,长度为顶点个数+1,下标为0的位置不存放

        for(int i=1;i<6;i++) {
            head[i]=new GraphLink();             //为第i个顶点创建链表
            System.out.print("顶点"+i+"=>");
            for(int j=0;j<data.length;j++) {     //寻找与该顶点相邻的顶点
                if(data[j][0]==i)                //起始顶点为i
                    head[i].insert(data[j][1]);  //终止顶点插入链表 
            }
            head[i].print();                     //每个顶点处理完后输出该顶点的链表
        }
    }
}

class Node{
    int data;                                   //顶点
    Node next;

    public Node(int data) {
        this.data=data;
        this.next=null;
    }
}

class GraphLink{
    public Node first;                           //头节点
    public Node last;                            //尾节点

    public boolean isEmpty() {
        return first==null;
    }

    public void print() {                        //打印链表
        Node current=first;
        while(current!=null) {
            System.out.print("["+current.data+"]");
            current=current.next;
        }
        System.out.println();
    }

    public void insert(int data) {               //将节点插入链表
        Node newNode=new Node(data);
        if(this.isEmpty()) {                     //判断链表是否为空
            first=newNode;
            last=newNode;
        }
        else {                                   //尾插法
            last.next=newNode;
            last=newNode;
        }
    }
}

程序运行结果:
这里写图片描述

优点:

  • 和相邻矩阵相比较节省空间
  • 计算所有顶点的度时,其时间复杂度为O(n+e)

缺点:

  • 要求入度时,必须先求其反转表
  • 图形新边的加入和删除会改动到相关的表链接
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值