第二十七天(数据结构:图)

图:是一种非线性结构形式化的描述:   G={V,R}V:图中各个顶点元素(如果这个图代表的是地图,这个顶点就是各个点的地址)R:关系集合,图中顶点与顶点之间的关系(如果是地图,这个关系集合可能就代表的是各个地点之间的距离)在顶点与顶点之间的关系上面加上一个权值(w),这种权值代表的意义可能会不一样如果没有权值,顶点与顶点之间可能只有是否能到达的情况,但是不知道到达它需要的"距离"图是一个二元组:描述V(顶点的代号,我们需要一个"数组") 描述R(可能是两点之间的距离,我们也需要一个"数组"去描述)图分为两种1 有向图:关系是有方向的(你可以想象是一个单行道)有去不一定有来在画图的时候,关系是有箭头指向的2 无向图:关系是没有方向的(你可以想象是小区的小道,你过去是走这一条,回来的时候也是走的这一条)有去一定有来在画图的时候,关系是没有箭头指向的网:带权值的图我们就叫网顶点的度:有出度也有入度如果图是有向图,这个顶点有出度不一定有入度,有入度不一定有出度如果图是无向图,这个顶点有出度一定有入度一般图里面算度的数量的时候分别都要算入度和出度的数量出度:拓扑  --> 找一个没有入度的顶点出发通过出度到达另外一个顶点,然后将这个点的入度全部删除然后从下一个点继续开始,如果最后能将图里面的所有的顶点都遍历一遍那个这个图就叫拓扑有序,否则就叫拓扑无序入度:逆拓扑 -> 跟上面的是反的图:里面主要要搞定一个叫路径的问题1 最短路径 --- 最短的那一条2 关键路径 --- 在覆盖所有的工作流程里面找最短的那些路径这些路径里面最长的那条路径就叫关键路径计算机里面描述图图是一个二元组,因此需要用至少两个东西分别描述顶点元素集合,关系集合假设你的顶点是ABCDEFG -> 我们开一个char[]就可以描述了假设你的顶点是"长沙" "武汉"... -> char *[]描述假设你的关系集合为距离 -> int [][]我们有几种方式去做图的保存"数组表示法" -> 邻接矩阵"链表表示法" -> 邻接表(逆邻接表) 十字链表 邻接多重表邻接矩阵:通过顶点元素数组和关系集合数组来描述通过画图可以看出,邻接矩阵适合稠密图邻接表:通过顶点元素数组和关系链表来描述(有向图无向图都能做)十字链表:主要搞定有向图(可以快速反应这个点的入度与出度)邻接多重表:主要搞定无向图(有去必有来,因此可以少建立很多的关系)通过画图可以看出,链表表示法适合稀松图图的遍历1 深度优先DFS:树里面的先序遍历的扩展图里面的任何一个顶点都可能是出发点从出发点开始,将其遍历,然后以深度优先的方式继续遍历它的邻接点(和它有直接关系的点在画图的时候有一根线和它连起来了,这个点就是它的邻接点)邻接点遍历完毕继续以深度优先遍历它的邻接点的邻接点这个点有去也有可能有来,遍历的时候就可能会遇到刚刚遍历过点因此我们需要一个辅助向量来表明这个顶点是不是已经被遍历过了char V[10];visit[10] -> visit[0]表示V[0]是不是已经被访问 visit[1]表示V[1]是不是已经被访问.....0没有被遍历,1表示遍历过了if(visit[i] == 0){              访问V[i]visit[i] = 1;//标记已经被访问过DFS(V[i]的邻接点) //以相同的规则去访问这个邻接点}访问w;for(v = 从w第一个邻接点开始;v邻接点存在;v = w下一个邻接点){if(visit[v] == 0){//访问vvisit[v] == 1;DFS(v);}}2 广度优先BFS:树里面的层次遍历的扩展利用队列来进行每一层每一层的遍历入队访问出队访问都可以从起点开始,将它入队出队,转向它的下一辈(它所有的邻接点(前面有可能已经被访问过,访问过的要排除))为了确保孤岛也能被访问,我们需要将每一个点都要以BFS的形式走一遍BFS(v){//将顶点入队queue_push(v);while(队列不为空){v = queue_front();queue_pop();for(i = v的所有邻接点){if(visit[i] == 0) //这些邻接点没有被访问你才需要去访问{visit[i] = 1;queue_push(i);}}}}for(i < 顶点个数个数)//防止有孤岛  所以每一个点都要试一次BFS{if(visit[i] == 0){BFS(i);}}//输入格式
ABCDEFG ->所有的顶点元素
AB3     ->边以及权值
BC5
...
##-1退出
//你的图里面最多可以容纳的顶点个数
#define VMaxNum 1000//这个值代表一个无法到达的权值
#define VERYBIG 65535//弄的是邻接矩阵//你现在需要一个图的类型
typedef struct 
{char _V[VMaxNum];//顶点元素的数组int _R[VMaxNum][VMaxNum];//顶点与顶点之间的关系集合int _vexnum;//真正顶点的个数int _arcnum;//边(关系线)的个数  无向的叫边  有向的叫弧
}Graph;
#include "Graph.h"//建立邻接矩阵
Graph * GraphInit(void)
{return (Graph *)calloc(1,sizeof(Graph));
}//获取顶点元素的下标 -1表示失败
int GetVIndex(Graph * g,char v)
{for(int i = 0;i < g ->_vexnum;i++){if(v == g ->_V[i])return i;}return -1;
}//从键盘获取顶点元素以及边
void GetGraph(Graph * g)
{if(!g)return;printf("请输入所有的顶点元素:");scanf("%s",g ->_V);getchar();g ->_vexnum = strlen(g ->_V);//实际顶点个数为这么多//关系集合里面什么玩意儿都没有 不能是0for(int i = 0;i < g ->_vexnum;i++){for(int j = 0;j < g ->_vexnum;j++){g ->_R[i][j] = VERYBIG;//用VERYBIG将关系集合初始化一遍}}char start,stop;int w;while(1){printf("请输入边和权值(AB2):");if(scanf("%c%c%d",&start,&stop,&w) != 3){printf("\t\t输入有误,请重新输入\n");char buf[1024];fgets(buf,1024,stdin);continue;}getchar();//输入成功在后面会多一个\n 你需要拿走if('#' == start || '#' == stop || -1 == w){break;}//printf("%c  %c  %d\n",start,stop,w);int start_index = GetVIndex(g,start);int stop_index = GetVIndex(g,stop);if(-1 == start_index || -1 == stop_index){printf("\n边有问题,请重新输入\n");}//为了避免重复if(g ->_R[start_index][stop_index] == VERYBIG)g ->_arcnum++;g ->_R[start_index][stop_index] = w;//这个东西代表的是start到stop有w远printf("%d   %d\n",start_index,stop_index);g ->_R[stop_index][start_index] = w;//无向图就可以多这一步    }
}//打印邻接矩阵
void PrintGraph(Graph * g)
{if(!g)return;for(int i = 0;i < g ->_vexnum;i++){printf("\t%c",g ->_V[i]);}printf("\n");for(int i = 0;i < g ->_vexnum;i++){printf("%c",g ->_V[i]);for(int j = 0;j < g ->_vexnum;j++){if(g ->_R[i][j] == VERYBIG)printf("\t\\");elseprintf("\t%d",g ->_R[i][j]);}printf("\n");}
}//获取v的第一个邻接点 v这一行里面第一个不是VERYBIG的
//失败返回-1
int GetFirstIndex(Graph * g,int v)
{for(int i = 0;i < g ->_vexnum;i++){if(g ->_R[v][i] != VERYBIG)return i;}return -1;
}
//获取v的w的下一个邻接点 v这一行里面w列后面第一个不是VERYBIG的
//失败返回-1
int GetNextIndex(Graph * g,int v,int w)
{for(int i = w + 1;i < g ->_vexnum;i++){if(g ->_R[v][i] != VERYBIG)return i;}return -1;
}//遍历的向量
int visit[VMaxNum];//visit[i]表示顶点V[i]是否被访问 0表示没有  1表示访问过了//这里用的v是下标
static void DFS(Graph * g,int v)
{if(!g || visit[v])//已经访问过就不用访问了return;printf("%c ",g ->_V[v]);visit[v] = 1;for(int w = GetFirstIndex(g,v);w > -1;w = GetNextIndex(g,v,w)){if(visit[w] == 0){DFS(g,w);}}
}//DFS 深度优先 从v开始进行DFS  v是顶点
void DFS_search(Graph * g,char v)
{//初始化visitmemset(visit,0,g ->_vexnum *sizeof(visit[0]));printf("DFS:");//先弄一个遍v开始的DFSDFS(g,GetVIndex(g,v));printf("\n");//所有再遍历来一遍for(int i = 0;i < g ->_vexnum;i++){if(visit[i] == 0){DFS(g,i);printf("\n");}}
}//请你实现BFS
static void BFS(Graph * g,int v)
{if(!g || visit[v])//图不存在或者v被访问过都无需访问return;//队列要存在ArrayQueue * qu = ArrayQueue_init(100);//将顶点入队ArrayQueue_push(qu,v);visit[v] = 1;while(!ArrayQueue_empty(qu)){v = ArrayQueue_front(qu);printf("%c ",g ->_V[v]);ArrayQueue_pop(qu);//for(int i = GetFirstIndex(g,v);i > -1;i = GetNextIndex(g,v,i))for(int i = 0;i < g ->_vexnum;i++){if(g ->_R[v][i] != VERYBIG){if(visit[i] == 0) //这些邻接点没有被访问你才需要去访问{visit[i] = 1;ArrayQueue_push(qu,i);}}}      }ArrayQueue_destory(&qu,NULL);
}//BFS 广度优先 从v开始进行BFS  v是顶点
void BFS_search(Graph * g,char v)
{//初始化visitmemset(visit,0,g ->_vexnum *sizeof(visit[0]));printf("BFS:");//先弄一个遍v开始的BFSBFS(g,GetVIndex(g,v));printf("\n");//所有再遍历来一遍for(int i = 0;i < g ->_vexnum;i++)//防止孤岛{if(visit[i] == 0){BFS(g,i);printf("\n");}  }}

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

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

相关文章

数据赋能(386)——数据挖掘——迭代过程

概述重要性如下&#xff1a;提升挖掘效果&#xff1a;迭代过程能不断优化数据挖掘模型&#xff0c;提高挖掘结果的准确性和有效性&#xff0c;从而更好地满足业务需求。适应复杂数据&#xff1a;数据往往具有复杂性和多样性&#xff0c;通过迭代可以逐步探索和适应数据的特点&a…

什么是键值缓存?让 LLM 闪电般快速

一、为什么 LLMs 需要 KV 缓存&#xff1f;大语言模型&#xff08;LLMs&#xff09;的文本生成遵循 “自回归” 模式 —— 每次仅输出一个 token&#xff08;如词语、字符或子词&#xff09;&#xff0c;再将该 token 与历史序列拼接&#xff0c;作为下一轮输入&#xff0c;直到…

16.Home-懒加载指令优化

问题1&#xff1a;逻辑书写位置不合理问题2&#xff1a;重复监听问题已经加载完毕但是还在监听

Day116 若依融合mqtt

MQTT 1.MQTT协议概述MQTT是一种基于发布/订阅模式的轻量级消息传输协议&#xff0c;设计用于低带宽、高延迟或不稳定的网络环境&#xff0c;广泛应用于物联网领域1.1 MQTT协议的应用场景1.智能家居、车联网、工业物联网&#xff1a;MQTT可以用于连接各种家电设备和传感器&#…

PyTorch + PaddlePaddle 语音识别

PyTorch PaddlePaddle 语音识别 目录 概述环境配置基础理论数据预处理模型架构设计完整实现案例模型训练与评估推理与部署性能优化技巧总结 语音识别&#xff08;ASR, Automatic Speech Recognition&#xff09;是将音频信号转换为文本的技术。结合PyTorch和PaddlePaddle的…

施耐德 Easy Altivar ATV310 变频器:高效电机控制的理想选择(含快速调试步骤及常见故障代码)

施耐德 Easy Altivar ATV310 变频器&#xff1a;高效电机控制的理想选择&#xff08;含快速调试步骤&#xff09;在工业自动化领域&#xff0c;变频器作为电机控制的核心设备&#xff0c;其性能与可靠性直接影响整个生产系统的效率。施耐德电气推出的 Easy Altivar ATV310 变频…

搭建邮件服务器概述

一、电子邮件应用解析标准邮件服务器&#xff08;qq邮箱&#xff09;&#xff1a;1&#xff09;提供电子邮箱&#xff08;lvbuqq.com&#xff09;及存储空间2&#xff09;为客户端向外发送邮件给其他邮箱&#xff08;diaochan163.com&#xff09;3&#xff09;接收/投递其他邮箱…

day28-NFS

1.每日复盘与今日内容1.1复盘Rsync:本地模式、远程模式&#x1f35f;&#x1f35f;&#x1f35f;&#x1f35f;&#x1f35f;、远程守护模式&#x1f35f;&#x1f35f;&#x1f35f;&#x1f35f;&#x1f35f;安装、配置Rsync启动、测试服务备份案例1.2今日内容NFS优缺点NFS服…

二叉搜索树--通往高阶数据结构的基石

目录 前言&#xff1a; 1、二叉搜索树的概念 2、二叉搜索树性能分析 3、二叉搜索树的实现 BinarySelectTree.h test.cpp 4、key 和 key / value&#xff08; map 和 set 的铺垫 &#xff09; 前言&#xff1a; 又回到数据结构了&#xff0c;这次我们将要学习一些复杂的…

Profinet转Ethernet IP网关接入五轴车床上下料机械手控制系统的配置实例

本案例为西门子1200PLC借助PROFINET转EtherNet/IP网关与搬运机器人进行连接的配置案例。所需设备包括&#xff1a;西门子1200PLC、Profinet转EtherNet/IP网关以及发那科&#xff08;Fanuc&#xff09;机器人。开启在工业自动化控制领域广泛应用、功能强大且专业的西门子博图配置…

专题二_滑动窗口_长度最小的子数组

引入&#xff1a;滑动窗口首先&#xff0c;这是滑动窗口的第一道题&#xff0c;所以简短的说一下滑动窗口的思路&#xff1a;当我们题目要求找一个满足要求的区间的时候&#xff0c;且这个区间的left和right指针&#xff0c;都只需要同向移动的时候&#xff0c;就可以使用滑动窗…

解锁高效开发:AWS 前端 Web 与移动应用解决方案详解

告别繁杂的部署与运维&#xff0c;AWS 让前端开发者的精力真正聚焦于创造卓越用户体验。在当今快速迭代的数字环境中&#xff0c;Web 与移动应用已成为企业与用户交互的核心。然而&#xff0c;前端开发者常常面临诸多挑战&#xff1a;用户认证的复杂性、后端 API 的集成难题、跨…

北京JAVA基础面试30天打卡04

1. 单例模式的实现方式及线程安全 单例模式&#xff08;Singleton Pattern&#xff09;确保一个类只有一个实例&#xff0c;并提供一个全局访问点。以下是常见的单例模式实现方式&#xff0c;以及如何保证线程安全&#xff1a; 单例模式的实现方式饿汉式&#xff08;Eager Init…

Redis 缓存三大核心问题:穿透、击穿与雪崩的深度解析

引言在现代互联网架构中&#xff0c;缓存是提升系统性能、降低数据库压力的核心手段之一。而 Redis 作为高性能的内存数据库&#xff0c;凭借其丰富的数据结构、灵活的配置选项以及高效的网络模型&#xff0c;已经成为缓存领域的首选工具。本文将从 Redis 的基本原理出发&#…

耘瞳科技国产化点云处理软件,开启智能化三维测量新时代

在现代工业制造领域&#xff0c;三维点云数据已成为推动生产效率提升、质量控制优化以及智能制造转型的关键技术之一。三维点云数据能够提供高精度的物体表面信息&#xff0c;广泛应用于制造零件的质量检测&#xff1b;通过点云数据与CAD模型的对比分析&#xff0c;可以快速检测…

RabbitMQ面试精讲 Day 8:死信队列与延迟队列实现

【RabbitMQ面试精讲 Day 8】死信队列与延迟队列实现 文章标签 RabbitMQ,消息队列,死信队列,延迟队列,面试技巧,分布式系统 文章简述 本文是"RabbitMQ面试精讲"系列第8天&#xff0c;深入讲解死信队列与延迟队列的实现原理与实战应用。文章详细解析死信队列的触发…

团结引擎 1.5.0 版本发布:Android App View 功能详解

核心亮点 原生安卓应用支持 2D & 3D 双形态呈现 编辑器全流程集成 灵活调控功能 多应用并行展示 智能座舱应用示例 快速入门指南 开发说明 功能支持 实验性功能 资源链接 团结引擎 1.5.0 版本已于 4 月 14 日正式上线。本次更新中&#xff0c;车机版引入了一项突…

基于SpringBoot的OA办公系统的设计与实现

文章目录前言详细视频演示具体实现截图后端框架SpringBoot持久层框架MyBaits成功系统案例&#xff1a;代码参考数据库源码获取前言 博主介绍:CSDN特邀作者、985高校计算机专业毕业、现任某互联网大厂高级全栈开发工程师、Gitee/掘金/华为云/阿里云/GitHub等平台持续输出高质量…

知识随记-----用 Qt 打造优雅的密码输入框:添加右侧眼睛图标切换显示

Qt 技巧&#xff1a;通过 QLineEdit 右侧眼睛图标实现密码可见性切换 文章目录Qt 技巧&#xff1a;通过 QLineEdit 右侧眼睛图标实现密码可见性切换概要整体架构流程技术名词解释技术细节实现效果展示概要 本文介绍如何使用 Qt 框架为 QLineEdit 控件添加一个右侧的眼睛图标&a…

Unity里的对象旋转数值跳转问题的原理与解决方案

文章目录1. 问题描述2. 问题原因3. 解决方案3.1通过多个父子关系从而控制旋转&#xff08;推荐&#xff09;3.2 使用四元数进行旋转1. 问题描述 我们现在写一个3D的Unity程序&#xff0c;我们现在设置了一个物体后&#xff0c;我们想旋转使其改为我们想要的情况。但是我们如果…