JAVA 数据结构 12-图的实现、深度遍历DFS、广度遍历BFS

JAVA 数据结构 12-图

--图创建、深度、广度遍历完整代码见最后

问题:为什么要有图?

线性表局限于一个直接前驱和一个直接后继的关系,当我们需要表示多对多的关系时,就需要用到图的结构。

图的基本介绍:

​ 图是一种数据结构,其中结点可以具有零个或多个相邻元素。两个结点之间的连接称为边。结点也可以称为顶点。如图:

在这里插入图片描述

图的表示方式

​ 图的表示方式有两种:二维数组表示(邻接矩阵)和链表表示(邻接表

  1. 邻接矩阵是表示图中顶点之间直接相邻关系的矩阵,对于n个顶点的图而言,矩阵的行和列表示第n个点。若矩阵中值为1,则表示当前行和列的结点之间有边。

在这里插入图片描述

  1. 邻接表的实现只关心存在的边,为每一个结点创建一条链表,将与该结点有边的结点记录在链表上。

在这里插入图片描述

1. 实现图结构

在这里插入图片描述

要求:代码实现上图中的图结构

思路分析

  • 需要一个存储结点信息的集合;
  • 需要一个存储边信息的集合(顶点之间的关系);
  • 顶点信息使用ArrayList保存;
  • 边信息采用邻接矩阵int[][]的方式进行存储。

代码实现

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Graph {
   
    private List<String> vertexList;    //顶点集合
    private int[][] edges;  //边集合
    private int numOfEdges; //边的数目
    public  static void main(String args[]){
   
        Graph graph = new Graph(5);
        //添加点
        graph.addVertex("A");graph.addVertex("B");
        graph.addVertex("C");graph.addVertex("D");graph.addVertex("E");
        //添加边
        graph.addEdge("A","B",1);graph.addEdge("A","C",1);
        graph.addEdge("B","C",1);graph.addEdge("B","D",1);
        graph.addEdge("B","E",1);
        //展现邻接矩阵
        graph.showEdges();
    }
    public Graph(int n){
   
        this.vertexList = new ArrayList<>();
        this.edges = new int[n][n];
        this.numOfEdges = 0;
    }
    public void showEdges(){
   
        for (int[] arr:this.edges){
   
            System.out.println(Arrays.toString(arr));
        }
    }
    public void addVertex(String value){
   
        vertexList.add(value);
    }
    /**
     * 添加无向边
     * @param v1    顶点1
     * @param v2    顶点2
     * @param weight    权值
     */
    public void addEdge(String v1,String v2, int weight){
   
        int index1 = vertexList.indexOf(v1);
        int index2 = vertexList.indexOf(v2);
        this.edges[index1][index2] = weight;
        this.edges[index2][index1] = weight;
        numOfEdges++;
    }
}

2. 图的深度优先遍历(DFS)使用栈递归实现

算法思想:从初始访问结点出发,初始访问结点可能有多个邻接结点,首先啊访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接结点。每次都在访问完当前结点后首先访问当前结点的第一个邻接结点。算法策略优先从纵向挖掘深度,而不是对一个结点的所有邻接结点进行横向访问。

实现思路分析

  1. 访问初始结点v,并标记结点v为已访问;
  2. 查找结点v的i一个邻接结点w;
  3. 若w存在,则继续执行4,如果w不存在,则回到第一步,将从v的下一个结点继续;
  4. 若w未被访问,对w进行深度优先遍历递归(将w看作初始结点,重复步骤123);
  5. 若w已经被访问,查找v的下一个邻接点,转到步骤3.

代码实现

前提方法:得到第一个邻接点的下标

	/**
     * 找第一个邻接点的下标,如果没找到返回-1
     * @param index 当前点
     * @return
     */
    public int getFirstNeighbor(int index){
   
        for(int i = 0;i<vertexList.size();i++){
   
            if
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值