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

图是一种数据结构;

有向图
带权图

邻接矩阵

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

邻接表

图的深度优先遍历(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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

图论06-【无权无向】-图的遍历并查集Union Find-力扣695为例

文章目录 1. 代码仓库2. 思路2.1 UF变量设计2.2 UF合并两个集合2.3 查找当前顶点的父节点 find(element) 3. 完整代码 1. 代码仓库 https://github.com/Chufeng-Jiang/Graph-Theory 2. 思路 2.1 UF变量设计 parent数组保存着每个节点所指向的父节点的索引&#xff0c;初始值为…

改善游戏体验:数据分析与可视化的威力

当今&#xff0c;电子游戏已经超越了娱乐&#xff0c;成为一种文化现象&#xff0c;汇聚了全球数十亿的玩家。游戏制作公司正采用越来越复杂的技术来提高游戏质量&#xff0c;同时游戏数据分析和可视化工具变得不可或缺。 数据的力量&#xff1a;解析游戏体验 游戏制作涉及到大…

BadNets:基于数据投毒的模型后门攻击代码(Pytorch)以MNIST为例

加载数据集 # 载入MNIST训练集和测试集 transform transforms.Compose([transforms.ToTensor(),]) train_loader datasets.MNIST(rootdata,transformtransform,trainTrue,downloadTrue) test_loader datasets.MNIST(rootdata,transformtransform,trainFalse) # 可视化样本 …

关于本地项目上传到gitee的详细流程

如何上传本地项目到Gitee的流程&#xff1a; 1.Gitee创建项目 2. 进入所在文件夹&#xff0c;右键点击Git Bash Here 3.配置用户名和邮箱 在gitee的官网找到命令&#xff0c;注意这里的用户名和邮箱一定要和你本地的Git相匹配&#xff0c;否则会出现问题。 解决方法如下&…

【机器学习合集】泛化与正则化合集 ->(个人学习记录笔记)

文章目录 泛化与正则化1. 泛化(generalization)2. 正则化方法2.1 显式正则化方法显式正则化方法对比提前终止模型的训练多个模型集成Dropout技术 2.2 参数正则化方法2.3 隐式正则化方法方法对比 泛化与正则化 1. 泛化(generalization) 泛化不好可能带来的问题 模型性能不稳定容…

VNC图形化远程连接Ubuntu服务器

我的Ubuntu版本22.04.3&#xff0c;带有gnome图形桌面。配置过程参考了几篇博客&#xff0c;大致流程如下。因为是配置完之后才整理的流程&#xff0c;可能有疏漏。 Ubuntu服务器上的配置 1.先在服务器上下载vnc server&#xff08;任何一种版本均可&#xff09; vncserver有…

【管理运筹学】第 10 章 | 排队论(4,系统容量有限制和顾客源有限的情形)

文章目录 引言一、系统的容量有限制&#xff08; M / M / 1 / N / ∞ M/M/1/N/\infty M/M/1/N/∞&#xff09;二、顾客源为有限的情形&#xff08; M / M / 1 / ∞ / m M/M/1/\infty/m M/M/1/∞/m&#xff09;写在最后 引言 了解了标准的 M / M / 1 M/M/1 M/M/1 模型后&#…

【Java集合类面试二十四】、ArrayList和LinkedList有什么区别?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;ArrayList和LinkedList有…

k8s的coreDNS添加自定义hosts

1.ack的hosts不会继承宿主机的hosts&#xff0c;而工作中有一个域名默认是走内网解析&#xff0c;内网被限制访问了&#xff0c;只能在coreDNS中加一个hosts解析域名 2.编辑configmap (coredns) kubectl edit configmap -n kube-system coredns 增加hosts节点 Corefile: |.:53…

PDF 文档处理:使用 Java 对比 PDF 找出内容差异

不论是在团队写作还是在个人工作中&#xff0c;PDF 文档往往会经过多次修订和更新。掌握 PDF 文档内容的变化对于管理文档有极大的帮助。通过对比 PDF 文档&#xff0c;用户可以快速找出文档增加、删除和修改的内容&#xff0c;更好地了解文档的演变过程&#xff0c;轻松地管理…

html 常见兼容性问题

目录 前言: 用法: 代码: 1. 盒模型差异: 2. 表格布局问题: 3. 浏览器前缀问题: 4. 字体渲染问题: 理解: 讨论: 前言: 在Web开发中&#xff0c;兼容性问题是常见的挑战之一。不同的浏览器和设备可能以不同的方式解释和呈现HTML&#xff0c;导致网页在某些环境下出现问题…

第12章 PyTorch图像分割代码框架-1

从本章开始&#xff0c;本书将会进行深度学习图像分割的实战阶段。PyTorch作为目前最为流行的一款深度学习计算框架&#xff0c;在计算机视觉和图像分割任务中已经广泛使用。本章将介绍基于PyTorch的深度学习图像分割代码框架&#xff0c;在总体框架的基础上&#xff0c;基于PA…

Fabric.js 讲解官方demo:Stickman

本文简介 戴尬猴&#xff0c;我是德育处主任 Fabric.js 官网有很多有趣的Demo&#xff0c;不仅可以帮助我们了解其功能&#xff0c;还可以为我们提供创意灵感。其中&#xff0c;Stickman是一个非常有趣的例子。 先看看效果图 从上图可以看出&#xff0c;在拖拽圆形时&#xf…

yyds,Elasticsearch Template自动化管理新索引创建

一、什么是Elasticsearch Template&#xff1f; Elasticsearch Template是一种将预定义模板应用于新索引的功能。在索引创建时&#xff0c;它可以自动为新索引应用已定义的模板。Template功能可用于定义索引的映射、设置和别名等。它是一种自动化管理索引创建的方式&#xff0…

CSDN学院 < 华为战略方法论进阶课 > 正式上线!

目录 你将收获 适用人群 课程内容 内容目录 CSDN学院 作者简介 你将收获 提升职场技能提升战略规划的能力实现多元化发展综合能力进阶 适用人群 主要适合公司中高层、创业者、产品经理、咨询顾问&#xff0c;以及致力于改变现状的学员。 课程内容 本期课程主要介绍华为…

非侵入式负荷检测与分解:电力数据挖掘新视角

电力数据挖掘 概述案例背景分析目标分析过程数据准备数据探索缺失值处理 属性构造设备数据周波数据模型训练 性能度量推荐阅读 主页传送门&#xff1a;&#x1f4c0; 传送 概述 摘要&#xff1a;本案例将根据已收集到的电力数据&#xff0c;深度挖掘各电力设备的电流、电压和功…

03.MySQL事务及存储引擎笔记

事务 查看/设置事务 select autocommit; --查看当前数据库的事务状态&#xff0c;1表示开启&#xff0c;0表示关闭 set autocommit 0; --关闭自动事务提交采用关闭自动事务提交我们就可以手动进行事务提交&#xff0c;但是这种设置方式是对整个数据库起作用&#xff0c;一些可…

MongoDB 的集群架构与设计

一、前言 MongoDB 有三种集群架构模式&#xff0c;分别为主从复制&#xff08;Master-Slaver&#xff09;、副本集&#xff08;Replica Set&#xff09;和分片&#xff08;Sharding&#xff09;模式。 Master-Slaver 是一种主从复制的模式&#xff0c;目前已经不推荐使用。Re…

互联网产品说明书指南,附撰写流程与方法

产品说明书&#xff0c;对于普通产品而言&#xff0c;再常见不过。药物、电器、电子产品等产品在正式出售时&#xff0c;往往都会附带一份产品说明书&#xff0c;以此告诉用户这个产品的功能与特性&#xff0c;并指导用户如何来使用这个产品。 产品说明书 那么&#xff0c;对于…

Python遍历删除列表元素的一个奇怪bug

假定有一个Python列表&#xff0c;比如[CFFEX.IF, CFFEX.TS,SHFE.FU]&#xff0c;现在需要将其中带‘CFFEX’前缀的所有元素都删除。在使用列表推导式一行代码搞定之前&#xff0c;用了一种最朴素的遍历删除方法&#xff0c;结果出现了意想不到的的问题。复盘了下&#xff0c;结…