图(无向网)的邻接表方式存储,以及邻接表的深度、广度优先遍历方法-java

/**
 * 图(无向网)的邻接表存储结构
 */
public class AdjacencyListGraph {

    // 邻接表的顶点数组
    vertexNode[] vexs;

    int vexNums,arcNums;

    // 顶点数组的元素类
    class vertexNode{
        // 数据域
        char data;
        // 存放由该结点的邻接点组成的单链表的头指针
        // head只是为了方便操作的一个单链表头指针,其中不存放任何有意义的值,head之后的结点存储的才是真正的邻接点域
        ListNode head;
        public vertexNode(char data){
            this.data=data;
            this.head=new ListNode();
        }
    }

    // 邻接点单链表的元素类
    class ListNode{
        // 存放当前邻接点在顶点数组中的下标位置
        int pos;
        // 存放指向下一个邻接点的指针
        ListNode next;
        // 存放权值
        int info;

        public ListNode(){}

        public ListNode(int pos, ListNode next, int info){
            this.pos=pos;
            this.next=next;
            this.info=info;
        }
    }

    public AdjacencyListGraph(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(j, null, w);
            p=vexs[i].head;
            listNode_i.next=p.next;
            p.next=listNode_i;

            // 因为无向网的边的两个顶点是互为邻接点的,所以也要给下标为j的顶点添加邻接点,它的邻接点下标为i
            ListNode listNode_j = new ListNode(i, null, w);
            p=vexs[j].head;
            listNode_j.next=p.next;
            p.next=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;
    }

    /**
     * 邻接表的深度优先遍历
     * 从代码实现逻辑可以看出,深度优先遍历类似于树的先序遍历,
     * 1.每次先访问顶点(根节点),然后访问它的邻接点(子树),直至当前顶点的邻接点都被访问过(到达叶子结点),
     * 2.然后返回上一层,递归地进行第1步,直至所有顶点都被遍历过
     * @param vex 起点
     * @param visited 辅助数组,用以标识顶点是否被访问过
     */
    public void DFS(int vex,int[] visited){
        visited[vex]=1;
        System.out.println("访问了"+vexs[vex].data);
        ListNode p = vexs[vex].head;
        while(p.next!=null){
            p=p.next;
            if(visited[p.pos] == 0){
                DFS(p.pos, visited);
            }
        }
    }

    /**
     * 邻接表的广度优先遍历
     * 1.将起始点vertexNode入队,再将vertexNode出队
     * 2.先将对头出队,并将出队顶点设为p,遍历p的邻接点单链表,将所有未访问过的元素入队
     * 3.队列不为空,则重复第2步,直至队列为空,此时邻接表的广度优先遍历完成
     * 不同于邻接矩阵的是,在遍历邻接表并将邻接点入队时,只需判断该邻接点是否访问过即可
     * 因为邻接表只存储有效的邻接点
     * @param vex 起始顶点
     * @param queue 辅助队列
     * @param visited 辅助数组
     */
    public void BFS(int vex, Queue queue, int[] visited){
        // 起始点
        vertexNode vertexNode = vexs[vex];
        queue.add(vertexNode);
        visited[vex]=1;
        System.out.println("访问了"+vexs[vex].data);
        // 如果队列不为空
        while(!queue.isEmpty()){
            vertexNode p = (vertexNode) queue.poll();
            // 头指针
            ListNode head=p.head;
            while(head.next!=null){
                head=head.next;
                if(visited[head.pos]==0){
                    queue.add(vexs[head.pos]);
                    visited[head.pos]=1;
                    System.out.println("访问了"+vexs[head.pos].data);
                }
            }
        }
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        AdjacencyListGraph adjacencyListGraph=new AdjacencyListGraph(4);
        // 无向网的顶点集合
        String vexStr="ABCD";
        // 无向网的边集合,例如"A,B,4",A,B分别为边的两个顶点,4为此条边的权值
        String arcStr[]={"A,B,4","A,C,3","A,D,9","B,C,1","B,D,7","C,D,2"};
        adjacencyListGraph.init(vexStr,arcStr);
        System.out.println("图(无向网)初始化完成!");
        System.out.println("深度优先遍历:");
        adjacencyListGraph.DFS(3,new int[4]);
        System.out.println("广度优先遍历:");
        adjacencyListGraph.BFS(0,new ArrayDeque(),new int[4]);
    }
}

测试结果:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值