有向图的十字链表存储方式,以及统计图中顶点度的方法-java

有向图使用邻接表存储方式时,顶点的出度通过遍历它的邻接单链表可以实现,但是入度需要遍历所有邻接单链表才能得到
逆邻接表则相反,逆邻接表中顶点的入度易得到,出度则需要遍历所有单链表
十字链表可解决这一问题,十字链表中的每个节点既有一个指针指向以它本身为尾的边的链表(出度),也有一个指针指向以它本身尾头的边的链表(入度)
这样统计一个顶点的度就很方便,典型的使用空间换取时间。

/**
 * 有向图的十字链表存储方式

 */
public class AdjacencyCrossListGraph {
    // 邻接表的顶点数组
    VertexNode[] vexs;

    int vexNums,arcNums;

    class VertexNode{
        // 数据域
        char data;
        // 存放由该结点的邻接点组成的单链表的头指针
        // firstIn、firstOut只是为了方便操作的一个单链表头指针,其中不存放任何有意义的值,之后的结点存储的才是真正的邻接点域
        // firstIn指向顶点的入度边的链表
        ListNode firstIn;
        // firstOut指向顶点的出度边的链表
        ListNode firstOut;
        public VertexNode(char data){
            this.data=data;
            this.firstIn=new ListNode();
            this.firstOut=new ListNode();
        }
    }
    class ListNode{
        // 存放弧头顶点在顶点数组中的下标位置
        int headPos;
        // 存放弧尾顶点在顶点数组中的下标位置
        int tailPos;
        // 与这条边弧头顶点相同的边的指针
        ListNode hLink;
        // 与这条边弧尾顶点相同的指针
        ListNode tLink;
        // 存放权值
        int info;

        public ListNode(){
        }

        public ListNode(int headPos, int tailPos, ListNode hLink, ListNode tLink, int info) {
            this.headPos = headPos;
            this.tailPos = tailPos;
            this.hLink = hLink;
            this.tLink = tLink;
            this.info = info;
        }
    }

    public AdjacencyCrossListGraph(int n){
        vexs=new VertexNode[n];
    }

    /**
     * 初始化邻接表
     * @param vexStr 邻接表的顶点
     * @param arcStr 邻接表的边
     */
    public void init(String vexStr, String[] arcStr){
        for (int i = 0; i < vexs.length; i++) {
            vexs[i]=new VertexNode(vexStr.charAt(i));
            // 顶点的数量+1
            vexNums++;
        }

        // 初始化邻接链表
        // 先根据边的两个顶点的值,确定两个顶点在顶点表中的下标
        for (String s : arcStr) {
            // 顶点v1
            char v1=s.charAt(0);
            // 顶点v2
            char v2=s.charAt(2);
            // 权值
            int w=s.charAt(4)-'0';
            // 得到i,j
            int i=locateVex(v1);
            int j=locateVex(v2);

            ListNode p = null;

            // 给下标为i的顶点添加邻接点,邻接点下标为j
            ListNode listNode_i = new ListNode(i,j,null,null,w);
            // 出度<i,j>
            p=vexs[i].firstOut;
            listNode_i.tLink=p.tLink;
            p.tLink=listNode_i;

            // 入度<j,i>,给j顶点添加由i指向j的入度结点
            ListNode listNode_j = new ListNode(j, i, null, null, w);
            p=vexs[j].firstIn;
            listNode_j.hLink=p.hLink;
            p.hLink=listNode_j;

            // 边的数量+1
            arcNums++;
        }
    }

    private int locateVex(char v){
        for (int i = 0; i < vexs.length; i++) {
            if(v==vexs[i].data){
                return i;
            }
        }
        return -1;
    }

    /**
     * 统计顶点的入度个数
     * @return
     */
    public int inDegree(char v){
        int vexPos = locateVex(v);
        VertexNode vex = vexs[vexPos];
        ListNode in = vex.firstIn;
        int count=0;
        while(in.hLink!=null){
            count++;
            in=in.hLink;
        }
        return count;
    }

    /**
     * 统计顶点的出度个数
     * @return
     */
    public int outDegree(char v){
        int vexPos = locateVex(v);
        VertexNode vex = vexs[vexPos];
        ListNode in = vex.firstOut;
        int count=0;
        while(in.tLink!=null){
            count++;
            in=in.tLink;
        }
        return count;
    }

    /**
     * 统计顶点的度
     * @param v
     * @return
     */
    public int degree(char v){
        return this.inDegree(v)+this.outDegree(v);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值