图结构基本知识

news2024/9/28 19:15:02

  • 1. 相关概念
  • 2. 图的表示方式
  • 3. 图的遍历
    • 3.1 深度优先遍历(DFS)
    • 3.2 广度优先遍历(BFS)

1. 相关概念

  • 图G(V,E) :一种数据结构,可表示“多对多”关系,由顶点集V和边集E组成;
  • 顶点(vertex) :
  • 边 (edge):一幅点对(v,w),v,w∈V,边也称为弧;
  • 邻接:点v,w邻接,当且仅当边(v,w)∈E;
  • 路径 :由一个顶点序列v1,v2,…,vn组成,路径长为n-1;
  • 有向图 :边是单向的,点对有序;
  • 无向图 :边是双向的图,点对无序;
  • 带权图:不同边具有不同的权值的图;
  • 连通:无向图的一个顶点到其他任何顶点都存在一条路径,则称其为连通的;
  • 强连通:有向图的一个顶点到其他任何顶点都存在一条路径;
  • 弱连通:有向图本身不是强连通的,但是其边不考虑方向的无向图是连通的;
  • 完全图:每一对顶点间都存在边;

2. 图的表示方式

  • 邻接矩阵:使用二维数组实现,数组中每个元素表示图中两顶点之间是否有边,或者表示边的权值,适用于稠密图,对于稀疏图而言此表示方法过于浪费空间;

在这里插入图片描述

package com.northsmile.graph;

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

/**
 * Author:NorthSmile
 * Create:2023/4/18 9:17
 * 使用邻接矩阵表示图(无向图)
 */
public class Graph {
    // 存储边及其权值
    int[][] edges;
    // 存储顶点
    ArrayList<String> vertexes;
    // 记录边的数目
    int edgeNums;

    public Graph(int n){
        edges=new int[n][n];
        vertexes=new ArrayList<>(n);
        edgeNums=0;
    }

    /**
     * 插入顶点
     * @param vertex
     */
    public void insertVertex(String vertex){
        vertexes.add(vertex);
    }

    /**
     * 插入边
     * @param v1 边的一个顶点对应下标
     * @param v2 边的另一个顶点对应下标
     * @param w 边对应权值,默认为1
     */
    public void insertEdge(int v1,int v2,int w){
        edges[v1][v2]=w;
        edges[v2][v1]=w;
        edgeNums++;
    }

    /**
     * 获取顶点数量
     * @return
     */
    public int getVertexesNum(){
        return vertexes.size();
    }

    /**
     * 获取边的数目
     * @return
     */
    public int getEdgesNum(){
        return edgeNums;
    }

    /**
     * 获取指定下标对应的顶点的值
     * @param v
     * @return
     */
    public String getValByIndex(int v){
        return vertexes.get(v);
    }

    /**
     * 获取指定边的权值
     * @param v1
     * @param v2
     * @return
     */
    public int getWeightOfEdge(int v1,int v2){
        return edges[v1][v2];
    }

    /**
     * 显示表示图的邻接矩阵
     */
    public void showGraph(){
        for (int[] edge:edges){
            System.out.println(Arrays.toString(edge));
        }
    }
}

package com.northsmile.graph;

/**
 * Author:NorthSmile
 * Create:2023/4/18 9:18
 */
public class GraphDemo {
    public static void main(String[] args) {
        int n=5;
        String[] vertexes={"A","B","C","D","E"};
        Graph graph = new Graph(n);

        // 插入顶点
        for (String vertex:vertexes){
            graph.insertVertex(vertex);
        }
        // 插入边
        graph.insertEdge(0,1,1);
        graph.insertEdge(0,2,1);
        graph.insertEdge(1,2,1);
        graph.insertEdge(1,3,1);
        graph.insertEdge(1,4,1);
        graph.showGraph();
    }
}
  • 邻接表:使用数组+链表的方式实现,适用于稀疏图表示,是图的标准表示方法,对于每个顶点,将其所有邻接点使用一个表存放;
    在这里插入图片描述
package com.northsmile.graph;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * Author:NorthSmile
 * Create:2023/4/18 11:12
 * 使用邻接表表示图(有向图)
 */
public class GraphByAdjacenceList {
    // 邻接表
    HashMap<String,Vertex> list;
    int vertexNums;
    int edgeNums;

    public GraphByAdjacenceList(int n){
        list=new HashMap<>();
        vertexNums=n;
        edgeNums=0;
    }

    /**
     * 插入顶点
     * @param vertex
     */
    public void insertVertex(String vertex){
        list.put(vertex,new Vertex(vertexNums));
    }

    /**
     * 插入边
     * @param v 顶点
     * @param w 邻接点
     */
    public void insertEdge(String v,String w){
        Vertex vertex = list.get(v);
        vertex.table.add(w);
        edgeNums++;
    }

    /**
     * 获取顶点数量
     * @return
     */
    public int getVertexesNum(){
        return list.size();
    }

    /**
     * 获取边的数目
     * @return
     */
    public int getEdgesNum(){
        return edgeNums;
    }

    /**
     * 显示表示图的邻接表
     */
    public void showGraph(){
        for (String vertex:list.keySet()){
            System.out.println(vertex+":"+list.get(vertex).table);
        }
    }

    /**
     * 顶点类
     */
    class Vertex{
        ArrayList<String> table;

        public Vertex(int n){
            table=new ArrayList<>(n/2);
        }
    }
}

package com.northsmile.graph;

/**
 * Author:NorthSmile
 * Create:2023/4/18 9:18
 */
public class GraphDemo {
    public static void main(String[] args) {
        // 2.邻接表
        int n=5;
        String[] vertexes={"A","B","C","D","E"};
        GraphByAdjacenceList graph = new GraphByAdjacenceList(n);

        // 插入顶点
        for (String vertex:vertexes){
            graph.insertVertex(vertex);
        }
        // 插入边
        graph.insertEdge("A","B");
        graph.insertEdge("A","C");
        graph.insertEdge("B","C");
        graph.insertEdge("B","D");
        graph.insertEdge("B","E");
        graph.showGraph();
    }
}

3. 图的遍历

在这里插入图片描述

3.1 深度优先遍历(DFS)

  • 类似树的先序遍历,先访问当前顶点,再依次以其邻接点为新的起点,进行深度优先遍历;
  • 与树的遍历不同,图在深度优先遍历时,当前顶点的邻接点可能已经访问过,所以无需再进行访问;
  • 为了实现顶点的唯一遍历,在代码实现时需要提供一个标记数组,表示对应顶点是否已经访问过;
  • 代码实现以递归方式进行;
    在这里插入图片描述
    在这里插入图片描述
    /**
     * 深度优先遍历:类似树的先序遍历
     * @param v 以当前点开始遍历
     * @param visited 标记节点是否访问过
     */
    public void dfs(int v,boolean[] visited){
        System.out.print(vertexes.get(v)+"->");
        // 遍历当前顶点的邻接点
        for (int i=0;i<vertexes.size();i++){
            // 说明v、i之间存在边
            if (edges[v][i]!=0&&!visited[i]){
                visited[i]=true;
                dfs(i,visited);
            }
        }
    }

    public void dfs(){
        // 标记顶点是否已经访问过
        boolean[] visited=new boolean[vertexes.size()];
        // 以每个顶点开始进行DFS,实现图的完整遍历
        for (int i=0;i<vertexes.size();i++){
            if (!visited[i]){
                visited[i]=true;
                dfs(i,visited);
            }
        }
    }

3.2 广度优先遍历(BFS)

  • 类似树的层序遍历,先访问当前顶点,再依次访问其邻接点,然后分别以其邻接点为新的起点,继续进行广度优先遍历;
  • 与树的遍历不同,图在深度优先遍历时,当前顶点的邻接点可能已经访问过,所以无需再进行访问;
  • 为了实现顶点的唯一遍历,在代码实现时需要提供一个标记数组,表示对应顶点是否已经访问过;
  • 代码实现借助队列实现;
    在这里插入图片描述
    /**
     * 广度优先遍历:类似树的层次遍历
     * @param v 以当前点开始遍历
     * @param visited 标记节点是否访问过
     */
    public void bfs(int v,boolean[] visited){
        ArrayDeque<Integer> queue=new ArrayDeque<>();
        queue.offer(v);
        visited[v]=true;

        while (!queue.isEmpty()){
            Integer cur = queue.poll();
            System.out.print(vertexes.get(cur)+"->");
            // 遍历当前顶点的邻接点
            for (int i=0;i<vertexes.size();i++){
                // 说明v、i之间存在边
                if (edges[cur][i]!=0&&!visited[i]){
                    visited[i]=true;
                    queue.offer(i);
                }
            }
        }
    }

    public void bfs(){
        // 标记顶点是否已经访问过
        boolean[] visited=new boolean[vertexes.size()];
        // 以每个顶点开始进行BFS,实现图的完整遍历
        for (int i=0;i<vertexes.size();i++){
            if (!visited[i]){
                bfs(i,visited);
            }
        }
    }

资料来源:尚硅谷

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/429766.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库管理-第六十七期 SQL Domain 2(20230414)

数据库管理 2023-04-14第六十七期 SQL Domain 21 Domain函数示例总结第六十七期 SQL Domain 2 昨晚割接&#xff0c;搭了一套19c的ADG&#xff0c;今天睡了个懒觉&#xff0c;早上把笔记本内存扩到了64GB&#xff0c;主要是为了后面做实验。然后下午拼了个乐高&#xff0c;根据…

Excel小技巧:对比两列数据的异同、vlookup使用方法

目录 问题一&#xff1a; 在联盟对接的时候&#xff0c;团购站会推送一个返利值&#xff0c;称为“推送返利”&#xff0c;联盟后台又会计算一个返利值&#xff0c;称为“计算返利”。当团购站的推送返利与计算返利相同的时候&#xff0c;我们才认为这个团购站在返利上对接完…

JMeter全局变量在使用时第一次取到null的问题解决

1. 在执行JMeter测试时&#xff0c;登录操作只需要执行一次。这样就需要用到全局变量&#xff0c;但在前一个提取器执行了请求后&#xff0c;如果返回结果是json格式的数据&#xff0c;会在下面添加一个JSON提取器&#xff0c;并在json提取器下会添加一个后置BeanShell PostPro…

10个镜像网站工具箱供你使用,不注册ChatGPT也能免费使用ChatGPT

ChatGPT已经成为了人工智能技术中备受瞩目的一员&#xff0c;它可以为我们带来更加智能化、个性化的交互体验。对于没有ChatGPT账号或者不想注册账号的人来说&#xff0c;他们可能会错过这种神奇的体验。 而本篇文章就帮大家解决这个问题&#xff0c;不用登录ChatGPT账号&…

Spark 写 MySQL经典50题

目录 建表 & 添加数据 表结构分析图 连接数据库 题目 1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数 2、查询"01"课程比"02"课程成绩低的学生的信息及课程分数 3、查询平均成绩大于等于60分的同学的学生编号和学…

如何将GIS地图和可视化结合使用实现更好的数据呈现

GIS&#xff08;地理信息系统&#xff09;和可视化&#xff08;visualization&#xff09;是两个紧密相关的领域。GIS是一种用于管理、分析和展示地理空间数据的技术&#xff0c;而可视化则是一种用图形、图表、动画等形式展示数据的方式。GIS地图则是指基于地理信息系统技术&a…

【举一反三】只出现一次的数字

本文&#xff0c;讲位运算——异或运算。因为题干中说明要线性时间复杂度&#xff0c;所以采用位运算进行操作&#xff0c;而没有采用哈希表。 目录 1.只出现一次的数字 I 2.只出现一次的数字 II 3.只出现一次的数字 III 1.只出现一次的数字 I 136. 只出现一次的数字 - 力扣&…

浅析Dubbo核心设计

大家好&#xff0c;我是易安&#xff01; 当今互联网时代&#xff0c;随着企业业务的不断扩展和用户量的增加&#xff0c;分布式系统已成为大型企业必不可少的组成部分。而Dubbo框架作为阿里巴巴开源的高性能Java RPC框架&#xff0c;一直以来都备受关注和使用。其核心设计思想…

机器学习正以惊人的速度破解宇宙奥秘

宇航员、科学家和其他以探索并记录终极边界为己任的人们&#xff0c;才积极转向机器学习&#xff08;ML&#xff09;以协助应对自己面临的非凡挑战。从引导火箭穿越太空到研究遥远行星的表面&#xff0c;再到测量宇宙大小和计算天体的运动轨迹&#xff0c;AI在太空中拥有着众多…

300左右蓝牙耳机推荐,口碑好的平价蓝牙耳机选购指南

300元预算&#xff0c;想入手一款最值得蓝牙耳机&#xff0c;咋选&#xff1f;作为一个有4年玩机经验的爱好者&#xff0c;蓝牙耳机推荐性价比高的产品&#xff0c;今天就总结了几款目前很受欢迎&#xff0c;同时性能各方面都不错的机型&#xff0c;选对这几款&#xff0c;不用…

WIN10、WIN11 新电脑配置

WIN10、WIN11 新电脑配置WIN10、WIN11 新电脑配置开启管理员模式启用power shell脚本WIN10、WIN11 新电脑配置 开启管理员模式 WIN11 下没有安装本地安全策略组件&#xff0c;表现为CMD运行 secpol.msc 命令会提示异常 开启本地安全策略 echo off pushd "%~dp0"…

电脑上怎么把PDF转换成PPT?几步教你轻松转换

PDF文件是一种常见的办公文档格式&#xff0c;它具有固定格式和内容不易改变的特点&#xff0c;广泛应用于各种正式场合。虽然各种办公软件都能够将文件转换为PDF格式&#xff0c;但如果需要将PDF文件转换为其他格式&#xff0c;就需要使用专门的工具了。今天我们将介绍两款常用…

论文解读 | 解耦知识蒸馏

10 年来&#xff0c;DNN 的变革给计算机视觉领域带来了重大发展&#xff0c;促成了各种实时任务的繁荣&#xff0c;如图像分类、目标检测、语义分割等。然而强大的网络通常得益于大的网络容量&#xff0c;这通常以大量的计算和存储为代价&#xff0c;是工业应用所不喜欢的。在工…

一觉醒后ChatGPT 被淘汰了

OpenAI 的 Andrej Karpathy 都大力宣传&#xff0c;认为 AutoGPT 是 prompt 工程的下一个前沿。 近日&#xff0c;AI 界貌似出现了一种新的趋势&#xff1a;自主人工智能。 这不是空穴来风&#xff0c;最近一个名为 AutoGPT 的研究开始走进大众视野。特斯拉前 AI 总监、刚刚回归…

X进制转十进制黄金万能算法

单纯、混合进制通吃&#xff0c;真正的黄金万能的进制转换方法。 【学习的细节是欢悦的历程】Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅是基础那么简单…… 地址&#xff1a;https://…

LINUX_kali学习笔记

基础命令 命令说明示例pwd查看当前路径ls查看当前文件夹下文件 .开头为隐藏文件 &#xff08;文件夹下使用ctrlh查看&#xff09;ls -a&#xff08;查看文件及隐藏文件&#xff09;ls -alh&#xff08;查看文件及显示详情&#xff09;cd切换目录cd /&#xff08;切换到根目录&…

为何MySQL 8.0开始取消了查询缓存

官方文档说明&#xff1a;MySQL :: MySQL 8.0: Retiring Support for the Query Cache MySQL查询缓存是查询结果缓存。它将以SEL开头的查询与哈希表进行比较&#xff0c;如果匹配&#xff0c;则返回上一次查询的结果。 进行匹配时&#xff0c;查询必须逐字节匹配&#xff0c;例…

[Netty源码] 服务端启动过程 (二)

文章目录1.ServerBootstrap2.服务端启动过程3.具体步骤分析3.1 创建服务端Channel3.2 初始化服务端Channel3.3 注册selector3.4 端口绑定3.5 服务端的读事件1.ServerBootstrap ServerBootstrap引导服务端启动流程: //主EventLoopGroup NioEventLoopGroup master new NioEvent…

深入浅出:理解 RPC 和 Dubbo 架构

简介 Apache Dubbo是一款高性能的Java RPC框架.其前身是阿里巴巴公司开源的一个高性能,轻量级的开源Java RPC框架,可以和Spring框架无缝集成. Dubbo 官网 RPC RPC介绍 Remote Procedure Call 远程过程调用,是分布式架构的核心,按响应方式分以下两种: 同步调用:客户端调用…

App/Web自动化的面试题

App/Web自动化的面试题&#xff08;详细答案自己百度哈,红色的表示app自动化专有问题、绿色表示web自动化专有的问题&#xff0c;未标色的表示共有的问题&#xff09; 备注&#xff1a;一般面试的时候是结合简历上的项目一步一步深入进行问的问题&#xff0c;只要你实际做过一个…