数据结构和算法——图结构

news2025/1/11 7:11:51

图是一种数据结构;

有向图
带权图

邻接矩阵

邻接表相较于邻接矩阵,减少了存储空间;

邻接表

图的深度优先遍历(DFS)

图的广度优先遍历(BFS)

代码:

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

public class Graph {
    public static void main(String[] args) {

        int n = 8; // 节点的个数
        String[] vertexs = {"1", "2", "3", "4", "5", "6", "7", "8"};
        Graph graph = new Graph(n);
        // 添加顶点
        for (String VertexValue : vertexs) {
            graph.insertVertex(VertexValue);
        }
        graph.insertEdge(0, 1, 1);
        graph.insertEdge(0, 2, 1);
        graph.insertEdge(1, 3, 1);
        graph.insertEdge(1, 4, 1);
        graph.insertEdge(2, 5, 1);
        graph.insertEdge(2, 6, 1);
        graph.insertEdge(3, 7, 1);
        graph.insertEdge(4, 7, 1);
        graph.insertEdge(5, 6, 1);
        // 展示邻接矩阵
        graph.showGraph();
        graph.dfs();
//        graph.bfs();
    }

    private ArrayList<String> vertexList; //存储顶点的集合
    private int[][] edges; // 存储图的邻接矩阵
    private int numOfEdges; // 边的数量
    private boolean isVisited[]; // 是否被访问

    public Graph(int n) {
        edges = new int[n][n];
        vertexList = new ArrayList<>(n);
        numOfEdges = 0;
        isVisited = new boolean[n];
    }

    /**
     * 得到第一个邻接节点的下标
     *
     * @param index
     * @return
     */
    public int getFirstNeighbor(int index) {
        for (int j = 0; j < vertexList.size(); j++) {
            if (edges[index][j] > 0) {
                return j;
            }
        }
        return -1;
    }

    /**
     * 根据前一个邻接节点的下标来获取下一个邻接节点的下标
     *
     * @param v1
     * @param v2
     * @return
     */
    public int getNextNeighbor(int v1, int v2) {
        for (int j = v2 + 1; j < vertexList.size(); j++) {
            if (edges[v1][j] > 0) {
                return j;
            }
        }
        return -1;
    }


    /**
     * 深度优先遍历算法
     */
    public void dfs() {
        isVisited = new boolean[isVisited.length];
        for (int i = 0; i < getNumOfEdges(); i++) { // 节点个数5
            if (!isVisited[i]) {
                dfs(isVisited, i);
            }
        }
    }

    private void dfs(boolean[] isVisited, int i) {
        System.out.print(getValByIndex(i) + "->");
        // 将该节点设置为已访问
        isVisited[i] = true;
        // 查找节点i的第一个邻接节点
        int w = getFirstNeighbor(i);
        while (w != -1) {
            // 没有访问过
            if (!isVisited[w]) {
                dfs(isVisited, w);
            }
            // 邻接节点已经被访问过
            w = getNextNeighbor(i, w);
        }
    }

    /**
     * 遍历所有的节点,都进行广度优先搜索
     */
    public void bfs() {
        isVisited = new boolean[isVisited.length];
        for (int i = 0; i < getNumOfEdges(); i++) {
            if (!isVisited[i]) {
                bfs(isVisited, i);
            }
        }
    }

    /**
     * 对一个节点进行广度优先遍历的方法
     *
     * @param isVisited
     * @param i
     */
    private void bfs(boolean[] isVisited, int i) {
        int u; // 表示队列头节点对应的下标
        int w; // 邻接节点的下标
        // 队列,记录节点访问的顺序
        LinkedList<Integer> queue = new LinkedList<>();
        // 访问节点
        System.out.print(getValByIndex(i) + "=>");
        // 标记为已访问
        isVisited[i] = true;
        // 将节点加入队列
        queue.addLast(i);
        while (!queue.isEmpty()) {
            // 取出队列的头节点下标
            u = (Integer) queue.removeFirst();
            // 得到第一个邻接点的下标
            w = getFirstNeighbor(u);
            while (w != -1) {
                if (!isVisited[w]) {
                    System.out.print(getValByIndex(w) + "=>");
                    // 标记为已访问
                    isVisited[w] = true;
                    // 入队
                    queue.addLast(w);
                }
                // 以u为前驱点,找w后面的邻接点
                w = getNextNeighbor(u, w);
            }
        }
    }

    /**
     * 添加边
     *
     * @param v1     表示第一个顶点的下标
     * @param v2     表示第二个顶点的下标
     * @param weight 权值
     */
    public void insertEdge(int v1, int v2, int weight) {
        edges[v1][v2] = weight;
        edges[v2][v1] = weight; // 无向图
        numOfEdges++;
    }

    /**
     * 添加节点
     *
     * @param vertex
     */
    public void insertVertex(String vertex) {
        vertexList.add(vertex);
    }

    /**
     * 返回节点的个数
     *
     * @return
     */
    public int getNumOfEdges() {
        return vertexList.size();
    }

    /**
     * 返回节点i(下标)对应的数据
     *
     * @param i
     * @return
     */
    public String getValByIndex(int i) {
        return vertexList.get(i);
    }

    /**
     * 返回v1和v2的权值
     *
     * @param v1
     * @param v2
     * @return
     */
    public int getWeight(int v1, int v2) {
        return edges[v1][v2];
    }

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

参考视频:【尚硅谷】数据结构与算法(Java数据结构与算法)_哔哩哔哩_bilibili

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

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

相关文章

【定向征文活动】2023年深圳1024开发者城市聚会活动参会感想征文

深圳1024开发者城市聚会&#xff0c;有奖征文&#xff0c;欢迎大家来参与。 活动介绍 就在2023年10月22日&#xff0c;深圳COC社区与CSDN主办方联合发起了本年度深圳1024开发者城市聚会活动。活动一经发出&#xff0c;收到了小伙伴的热烈反响&#xff0c;一时间报名人数蹭蹭地…

墨西哥专线海运的集装箱尺寸选择

在国际贸易中&#xff0c;海运是一种常见的运输方式&#xff0c;而集装箱作为一种标准化的物流载具&#xff0c;其大小直接影响着货物的装卸和堆垛效率。对于需要通过墨西哥专线海运的客户来说&#xff0c;了解不同尺寸集装箱的优势和适用范围&#xff0c;可以帮助他们更有效地…

Java后端开发——房贷计算器(Ajax版、Json版、等额本息+等额本金)

MVC房贷计算器&#xff08;Ajax版&#xff09; 1.新建一个JavaWeb项目hslcalweb&#xff0c;设置tomcat10。 2.创建房贷计算器JavaBean&#xff1a;HslCalBean.java&#xff0c;增加以下的属性&#xff0c;并生成Getter/Setter方法。 private double total; //贷款额度pr…

Linux安装JumpServer

功能简介在线安装 环境要求&#xff1a;准备一台 2核4G &#xff08;最低&#xff09;且可以访问互联网的 64 位 Linux 主机 以 root 用户执行如下命令一键安装 JumpServer curl -sSL https://resource.fit2cloud.com/jumpserver/jumpserver/releases/latest/download/quick_st…

JAVA毕业设计102—基于Java+Springboot+vue的个人理财管理系统(源码+数据库)

基于JavaSpringbootvue的个人理财管理系统(源码数据库) 一、系统介绍 本系统前后端分离 管理员功能&#xff1a; 登录、注册、添加账单、导出账单、统计分析、个人信息修改、消费对比 二、所用技术 后端技术栈&#xff1a; SpringbootSpringMvcmybatismysql 前端技术栈…

优维低代码实践:父子模型

导语&#xff1a;优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学…

图片怎么做成动态gif?一招简单又高效

如何将静态图片变成gif动态图片&#xff1f;当下&#xff0c;各种各样的gif表情包充斥着我们的日常生活&#xff0c;但是有些gif动图不符合自己的需求&#xff0c;想要自己制作的时候应该怎么办呢&#xff1f;这时候&#xff0c;可以使用gif图片制作&#xff08;https://www.gi…

session和cookie机制

2023.10.23 域对象 先总结一下到目前位置我所了解的域对象&#xff1a; request&#xff08;对应的类名&#xff1a;HttpServletRequest&#xff09; 请求域&#xff08;请求级别的&#xff09; session&#xff08;对应的类名&#xff1a;HttpSession&#xff09; 会话域&am…

ITSource 分享 第1期【在线考试系统】

项目介绍 本期给大家介绍一个问卷调查系统. 一起来看看吧 ! 一 业务介绍 该系统分为以下几个模块: 1.我的问卷 image.png 可以查看创建的所有问卷, 包括 收集中,编辑中,已关闭等状态 2.创建问卷 image.png 问题类型可以选择有多种选择: 3.发布并填写问卷 问卷编辑完成后,即可保…

国内外CDN的发展

当今互联网世界中&#xff0c;内容交付网络&#xff08;Content Delivery Network&#xff0c;CDN&#xff09;已经成为网络加速的不可或缺的工具。CDN技术在国内外得到广泛应用&#xff0c;为了更好地了解CDN的不同之处以及未来的发展趋势&#xff0c;让我们深入探讨这一领域的…

Spring底层原理(三)

Spring底层原理(三) Bean的生命周期 SpringBootApplication public class Application {public static void main(String[] args) {ConfigurableApplicationContext context SpringApplication.run(Application.class, args);context.close();} } ​ Slf4j Component public…

MySQL身份验证绕过漏洞

搭建 vmihub靶场:vulhub靶场搭建与使用_剁椒鱼头没剁椒的博客-CSDN博客 运行漏洞: # 这里要改成自己的 /vulhub-master 存放目录 cd /etc/docker/vulhub-master/mysql/CVE-2012-2122# 关闭防火墙,不然就要放行3306端口 systemctl stop firewalld# 重启 Docker 服务 servic…

C# | Linq基本功 —— 必学的必熟的10个方法

C# Linq基本功 —— 必学的必熟的10个方法 文章目录 C# Linq基本功 —— 必学的必熟的10个方法1. Linq简介1.1 什么是Linq1.2 Linq的优势 2. Linq基本方法2.1 Where方法2.2 Select方法2.3 OrderBy方法2.4 GroupBy方法2.5 Join方法2.6 Any方法2.7 All方法2.8 First方法2.9 Skip方…

1024勋章

&#x1f338;关于重阳节的一些发疯日常&#xff08;昨天的聊天记录&#xff0c;今天发系列&#xff09;&#x1f605; &#x1f338;没错&#xff0c;发出来单纯觉得好玩儿&#x1f609;(为了1024勋章&#x1f60f;)芜湖&#xff01;

Kepware带你玩转IEC60870-104驱动

随着越来越多电力设备自动化程度的不断提高以及OPC协议的广泛应用&#xff0c;越多客户倾向于使用更为方便、快捷的方式去获取数据&#xff0c;IEC60870-5-104协议作为一个标准的电子自动化协议&#xff0c;在电力自动化现场应用非常广泛。 本文介绍KEPServerEX的IEC-104驱动&…

WeakMap 弱引用 不会被GC所考量

WeakMap是一种特殊的Map数据结构&#xff0c;只能以引用作为key&#xff0c;并且不会阻止其被垃圾回收。WeakMap的使用如下&#xff1a; 1. 创建WeakMap对象&#xff1a; const weakMap new WeakMap();2. 添加键值对&#xff1a;使用set()方法向WeakMap中添加键值对。注意这里…

c++ 模版的一些注意问题

声明和定义不可分离 举个例子&#xff1a; 定义一个Stack.h: 这里放声明 #include<iostream>using namespace std;template<class T> T Add(const T& left, const T& right);定义一个Stack.cpp, 这里面放定义: template<class T> T Add(const T&a…

虚拟机VMware Workstation Pro安装配置使用服务器系统ubuntu-22.04.3-live-server-amd64.iso

虚拟机里安装ubuntu-23.04-beta-desktop-amd64开启SSH(换源和备份)配置中文以及中文输入法等 ​一、获取Ubuntu服务器版 获取Ubuntu服务器版 二、配置虚拟机 选择Custom(advanced)&#xff1a; 选择Workstation 17.x: 选择“I will install the operating system later.”…

HashMap源码解析_jdk1.8(二)

HashMap源码解析_jdk1.8&#xff08;二&#xff09;构造函数put方法resize扩容方法 HashMap源码解析_jdk1.8&#xff08;二&#xff09; 构造函数 HashMap提供了如下几个构造函数&#xff1a; /*** 构造一个具有指定初始容量和负载因子的空HashMap.** param initialCapacit…

Android SystemUI setSystemUiVisibility()参数Flag详解

1&#xff1a;相关 Flag 特性详解 View.SYSTEM_UI_FLAG_LAYOUT_STABLE&#xff1a; 特性&#xff1a;默认状态下 &#xff0c;稳定页面显示布局。 当 StatusBar和 NavigationBar动态显示和隐藏时&#xff0c;系统为 fitSystemWindow“true”的view设置的padding大小都不会变化…