20240312-1-Graph(图)

Graph(图)

在这里插入图片描述

在面试的过程中,一般不会考到图相关的问题,因为图相关的问题难,而且描述起来很麻烦.
但是也会问道一下常见的问题,比如,最短路径,最小支撑树,拓扑排序都被问到过.

  1. 图常用的表示方法有两种: 分别是邻接矩阵和邻接表.
    邻接矩阵是不错的一种图存储结构,对于边数相对顶点较少的图,这种结构存在对存储空间的极大浪费.
    因此,找到一种数组与链表相结合的存储方法称为邻接表.

1. 最短路径

  • Dijkstra
  1. 维护一个最短路径的的集合(sptSet)和最短距离数组, 直到遍历所有的点, 初始化起始点的距离是0, 集合为空.
  2. 初始化起始点s到所有的点的距离是INF, 注意s到s的距离是0.
  3. while sptSet 不包含所有的顶点:
    • 选择当前能到达点的最小距离的点u,加入 sptSet
    • 使用u作为中间顶点,更新所有点的距离,选择最小距离的替换
    • dist[u]+graph[u][v] < dist[v]

百度百科
wikipedia

int minDistance(vector<int> dist, set<int> sptSet) {int min_d = INT_MAX, u;for(int i = 0, i < dist.size(); i ++) {if(sptSet.find(i) == sptSet.end() && dist[v] < min_d) {min_d = dist[i], u = i;}}return u;
}
// 使用vector 表示的邻接矩阵, return 起始点到所有点的最小距离
// 没有边的用0填充
vector<int> dijstra(vector<vector<int>> graph, set<int> &sptSet,int src) {int V = graph.size();vector<int> dist(V, 0);for(int i = 0;i < V; i ++) {if(i != src) dist[i] = INT_MAX;}while(sptSet.size() < V-1) {// pick mininum distance uint u = minDistance(dist, sptSet); sptSet.insert(u);// 使用u更新距离for(int v = 0; v < V; v ++) {if(sptSet.find(v)==sptSet.end() && graph[u][v] && dist[u] != INT_MAX&& dist[u]+graph[u][v] < dist[v]) {dist[v] = dist[u] + graph[u][v];}}}return dist;
}
  • Floyd Warshall
    Floyd算法是使用动态规划算法, dist[i][j]表示i–>j的最短距离,
    那么是否存在i–>k–>j的路径小于dist[i][j],于是就有了下面的更新公式,
  • if dist[i][k] + dist[k][j] < dist[i][j]:
    dist[i][j] = dist[i][k] + dist[k][j]

百度百科
wikipedia

void floydWarshall(vector<vector<int> > graph, vector<vector<int>> &dist, vector<vector<int> > &path) {int V = graph.size();// 参数dist和path需要初始化大小, 确定是否已经初始化vector<vector<int> > tmp(V, vector<int>(V));dist = path = tmp;for(int i = 0; i < V; i ++) {for(int j = 0; j < V; j ++) {dist[i][j] = graph[i][j];path[i][j] = j;}}for(int i = 0; i < V; i++) {for(int j = 0; j < V; j++) {for(int k = 0; k < V; k++) {if(dist[i][j] > dist[i][k] + dist[k][j]) {dist[i][j] = dist[i][k] + dist[k][j];pre[i][j] = pre[i][k];}}}}
}
//打印最短路径 u ---> v
int pfpath(int u, int v, vector<vector<int> > path) { while(u != v) {cout << u  << " ";u = path[u][v];}cout << u << endl;
}

2. 最小支撑树

  • Prim Algorithm
  1. 用一个集合mstSet维护已经满足要求的顶点
  2. 使用dist表示从mstSet集合某个点到u的最小距离为INF, 初始点Src的距离是0.
  3. while mstSet doesn’t include all vertices:
    • 选择一个不在mstSet中, 并且在dist中距离最小的顶点u, 加入到mstSet
    • 使用u更新dist距离, 表示从mstSet某个点到达为使用的点的最小距离

百度百科
wikipedia

int minDistance(vector<int> dist, set<int> mstSet) {int min_d = INT_MAX, u;for(int i = 0, i < dist.size(); i ++) {if(mstSet.find(i) == mstSet.end() && dist[v] < min_d) {min_d = dist[i], u = i;}}return u;
}
// 使用vector 表示的邻接矩阵, return 起始点到所有点的最小距离
// 没有边的用0填充
vector<int> dijstra(vector<vector<int>> graph, set<int> &mstSet,int src) {int V = graph.size();vector<int> dist(V, 0);int parent[V]; // 每个顶点的相邻的点parent[src] = -1;for(int i = 0;i < V; i ++) {if(i != src) dist[i] = INT_MAX;}while(mstSet.size() < V-1) {// pick mininum distance uint u = minDistance(dist, sptSet); mstSet.insert(u);// 使用u更新距离for(int v = 0; v < V; v ++) {if(mstSet.find(v)==mstSet.end() && graph[u][v] && graph[u][v] < dist[v]) {dist[v] = graph[u][v];parent[v] = u;}}}return dist;
}
  • Kruskal Algorithm
  1. 根据权重排序所有的边
  2. 选择一个小权重的边,如果它没有和最小支撑顶点形成环,就加入这个边
  3. 重复2,知道包含V-1个边

百度百科
wikipedia
Code 抄写

struct Edge { int src, dest, weight; 
}; 
struct Graph { int V, E;   struct Edge* edge; 
}; 
struct Graph* createGraph(int V, int E) { struct Graph* graph = new Graph; graph->V = V; graph->E = E;   graph->edge = new Edge[E]; return graph; 
} 
struct subset { int parent; int rank; 
}; 
int find(struct subset subsets[], int i) { if (subsets[i].parent != i) subsets[i].parent = find(subsets, subsets[i].parent); return subsets[i].parent; 
} 
void Union(struct subset subsets[], int x, int y) { int xroot = find(subsets, x); int yroot = find(subsets, y);   if (subsets[xroot].rank < subsets[yroot].rank) subsets[xroot].parent = yroot; else if (subsets[xroot].rank > subsets[yroot].rank) subsets[yroot].parent = xroot;   else { subsets[yroot].parent = xroot; subsets[xroot].rank++; } 
} 
int myComp(const void* a, const void* b) { struct Edge* a1 = (struct Edge*)a; struct Edge* b1 = (struct Edge*)b; return a1->weight > b1->weight; 
} 
void KruskalMST(struct Graph* graph) { int V = graph->V; struct Edge result[V];  int e = 0; int i = 0; qsort(graph->edge, graph->E, sizeof(graph->edge[0]), myComp);   struct subset *subsets = (struct subset*) malloc( V * sizeof(struct subset) ); for (int v = 0; v < V; ++v) { subsets[v].parent = v; subsets[v].rank = 0; }   while (e < V - 1) { struct Edge next_edge = graph->edge[i++];   int x = find(subsets, next_edge.src); int y = find(subsets, next_edge.dest);   if (x != y) { result[e++] = next_edge; Union(subsets, x, y); } }   return; 
} 

3. 拓扑排序

定义: 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。

  1. 计算所有节点的入度
  2. 每次选择一个入度为0的顶点u,如果的已经排序的结果中
  3. 将u所到达的所有顶点v,入度减1,
  4. 重复1,2,直到遍历所有顶点

百度百科
wikipedia

class Graph { int V;  // 顶点的个数list<int> *adj; // 所有顶点的起始指针
};void topologicalSort(int V, list<int> *adj) { // 计算所有入度vector<int> in_degree(V, 0);   for (int u=0; u<V; u++) { list<int>::iterator itr; for (itr = adj[u].begin(); itr != adj[u].end(); itr++) {in_degree[*itr]++; }} // 加入入度为0的点queue<int> q; for (int i = 0; i < V; i++) { if (in_degree[i] == 0) q.push(i); }int cnt = 0;   vector <int> top_order;   while (!q.empty()) { int u = q.front(); q.pop(); top_order.push_back(u);   // 所有连接点, 入度减去1list<int>::iterator itr; for (itr = adj[u].begin(); itr != adj[u].end(); itr++) {if (--in_degree[*itr] == 0) q.push(*itr); }cnt++; } if (cnt != V) { cout << "There exists a cycle in the graph\n"; return; }   for (int i=0; i<top_order.size(); i++) cout << top_order[i] << " "; cout << endl; 
} 

4. 有向图判环

题目: 请你判断一个 n 个点,m 条边的有向图是否存在环。参数为两个int数组,start[i]到end[i]有一条有向边.
解析: 这是拓扑排序的一种应用.

bool isCyclicGraph(vector<int> &start, vector<int> &end) {// 找到最大顶点值,构造图,int n = 0;for (int s : start) {n = max(n, s);}for (int e : end) {n = max(n, e);}// 构造图vector<vector<int>> graph(n + 1);vector<int> d(n + 1);int m = start.size();// 计算所有顶点的入度for (int i = 0; i < m; i++) {graph[start[i]].push_back(end[i]);d[end[i]]++;}queue<int> que;// 将所有入度为0的点,加入队列for (int i = 1; i <= n; i++) {if (graph[i].size() && !d[i]) {que.push(i);}}while (!que.empty()) {int h = que.front();que.pop();// 将多有入度为0的点,对应的顶点 入度减去1for (int y : graph[h]) {d[y]--;if (!d[y]) {que.push(y);}}}// 判断是否所有顶点的入度都是0, 如果是,则没有环,否则就有for (int i = 1; i <= n; i++) {if (d[i]) {return true;}}return false;
}

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

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

相关文章

【机器学习300问】33、决策树是如何进行特征选择的?

还记得我在【机器学习300问】的第28问里谈到的&#xff0c;看决策树的定义不就是if-else语句吗怎么被称为机器学习模型&#xff1f;其中最重要的两点就是决策树算法要能够自己回答下面两问题&#xff1a; 该选哪些特征 特征选择该选哪个阈值 阈值确定 今天这篇文章承接上文&…

学习 考证 帆软 FCP-FineBI V6.0 考试经验

学习背景&#xff1a; 自2024年1月起&#xff0c;大部分时间就在家里度过了&#xff0c;想着还是需要充实一下自己&#xff0c;我是一个充满热情的个体。由于之前公司也和帆软结缘&#xff0c;无论是 Fine-Report 和 Fine-BI 都有接触3年之久&#xff0c;但是主要做为管理者并…

第四弹:Flutter图形渲染性能

目标&#xff1a; 1&#xff09;Flutter图形渲染性能能够媲美原生&#xff1f; 2&#xff09;Flutter性能优于React Native? 一、Flutter图形渲染原理 1.1 Flutter图形渲染原理 Flutter直接调用Skia 1&#xff09;Flutter将一帧录制成SkPicture&#xff08;skp&#xff…

55. 跳跃游戏(力扣LeetCode)

文章目录 55. 跳跃游戏贪心每一次都更新最大的步数 取最大跳跃步数&#xff08;取最大覆盖范围&#xff09; 55. 跳跃游戏 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后…

【案例】IPC 中的WinCC RT Advanced PC项目,如何下载及开机自动启动?

导读&#xff1a;TIA WinCC Advanced (高级版)V17项目如何下载到目标计算机&#xff08;需要运行项目的电脑&#xff09;&#xff1f; 01WinCC RT Adv项目下载 1、在计算机开始菜单中点击“运行”或通过Win键R调出运行窗口&#xff0c;并输入 CMD 然后回车&#xff1a; 打开 W…

漏洞发现-漏扫项目篇NucleiYakitGobyAfrogXrayAwvs联动中转被动

知识点 1、综合类-Burp&Xray&Awvs&Goby 2、特征类-Afrog&Yakit&Nuclei 3、联动类-主动扫描&被动扫描&中转扫描 章节点&#xff1a; 漏洞发现-Web&框架组件&中间件&APP&小程序&系统 扫描项目-综合漏扫&特征漏扫&被动…

LED基础知识分享(一)

大家好&#xff0c;我是砖一。 今天给大家分享一下&#xff0c;LED的基础知识&#xff0c;有照明行业&#xff0c;或者对LED感兴趣的朋友&#xff0c;可以学习一下&#xff0c;希望对你有用~ 一&#xff0c;什么是LED (Light Emitting Diode)? 1&#xff0c;LED是一种发出某…

使用Flask快速搭建轻量级Web应用【第127篇—Flask】

使用Flask快速搭建轻量级Web应用 在Web开发领域&#xff0c;选择适合项目需求的框架至关重要。Flask&#xff0c;一个轻量级的Python Web框架&#xff0c;以其简洁、灵活和易扩展的特性而备受开发者青睐。本文将介绍如何使用Flask迅速搭建一个轻量级的Web应用&#xff0c;并通过…

【测试开发学习历程】Linux用户管理+文件权限管理

目录 一、用户管理 &#xff08;一&#xff09;用户和用户组的基本概念 1.概念 2.设置原因 3.用户与用户组的关系 4.用户类型 &#xff08;二&#xff09;用户的创建、修改属性和删除用户 1.用户信息文件 2.创建用户 3.修改用户密码 4.修改用户信息 5.用户查询 6.…

Hive面经

hive原理 Hive 内部表和外部表的区别Hive 有索引吗运维如何对 Hive 进行调度ORC、Parquet 等列式存储的优点数据建模用的哪些模型&#xff1f;1. 星型模型2. 雪花模型3. 星座模型 为什么要对数据仓库分层&#xff1f;使用过 Hive 解析 JSON 串吗sort by 和 order by 的区别数据…

Windows®、Linux® 和 UNIX® 系统都适用的远程桌面工具 OpenText ETX

Windows、Linux 和 UNIX 系统都适用的远程桌面工具 OpenText ETX 为 Windows、Linux 和 UNIX 实施精益、经济高效的虚拟化&#xff1b;提供完整的远程 Windows 可用性&#xff1b;以类似本地的性能远程工作&#xff1b;安全地保护系统和知识产权&#xff08;IP&#xff09;&am…

PFMEA的输入输出和特殊特性

DFMEA輸入&#xff1a;技术条件、市场需求 DFMEA輸出&#xff1a;产品特殊特性、试验、样件CPPFMEA輸入&#xff1a;过往经验、流程图、DPMEA PFMEA輸出&#xff1a;CP、过程特殊特性、SIP、SOP1. PFMEA的输入包括&#xff1a;&#xff08;&#xff09;过程流程图、DFMEA 、图样…

ElasticSearch 底层读写原理

ElasticSearch 底层读写原理 ​ 写请求是写入 primary shard&#xff0c;然后同步给所有的 replica shard&#xff1b;读请求可以从 primary shard 或 replica shard 读取&#xff0c;采用的是随机轮询算法。 1、ES写入数据的过程 1.选择任意一个DataNode发送请求&#xff0c…

Linux-gdb调试

文章目录 前言查看&#xff08;显示&#xff09;源代码 list/l运行程序run/r打断点b查看断点删除断点打开/关闭断点逐过程 逐语句查看变量常显示continuefinishuntil修改指定变量退出gdb 前言 GDB&#xff0c;即GNU调试器&#xff08;GNU Debugger&#xff09;&#xff0c;是G…

云仓酒庄最新动态:渠道商小沙龙活动持续开展 业务持续稳健发展

原标题&#xff1a;2024年云仓酒庄小沙龙活动持续开展 业务持续稳健发展 在风起云涌的酒类市场中&#xff0c;云仓酒庄以其独特的经营模式和优质的服务&#xff0c;赢得了广大消费者的青睐。而在这背后&#xff0c;云仓酒庄各地小沙龙活动的频繁开展&#xff0c;无疑为其业务的…

命名空间多线程计时(C++基础)

命名空间 不要在头文件内使用using namespace&#xff0c;一定要确保实在一个足够小的作用域下使用&#xff0c;在哪个范围内&#xff0c;比如函数、if语句等&#xff0c;但一定不要在头文件中使用&#xff01;&#xff01;&#xff01; 上述示例中&#xff0c;会调用orange中…

【位运算】【脑筋急转弯】2749. 得到整数零需要执行的最少操作数

作者推荐 视频算法专题 本文涉及知识点 2749. 得到整数零需要执行的最少操作数 给你两个整数&#xff1a;num1 和 num2 。 在一步操作中&#xff0c;你需要从范围 [0, 60] 中选出一个整数 i &#xff0c;并从 num1 减去 2i num2 。 请你计算&#xff0c;要想使 num1 等于 …

【Spring云原生系列】SpringBoot+Spring Cloud Stream:消息驱动架构(MDA)解析,实现异步处理与解耦合

&#x1f389;&#x1f389;欢迎光临&#xff0c;终于等到你啦&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;持续更新的专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &a…

FreeRTOS学习笔记-基于stm32(5)列表和列表项

一、列表与列表项简介 列表是FreeRTOS中的一种数据结构&#xff0c;类似双向循环链表。用来跟踪FreeRTOS中的任务。列表项就是存放在列表中的项目。 二、列表 列表结构体&#xff1a; typedef struct xLIST {listFIRST_LIST_INTEGRITY_CHECK_VALUE //校验值c…

强化学习工具箱(Matlab)

1、Get Started 1.1、MDP环境下训练强化学习智能体 MDP环境如下图 每个圆圈代表一个状态每个状态都有上或下的选择智能体从状态 1 开始智能体接收的奖励值为图中状态转移的值训练目标是最大化累计奖励 &#xff08;1&#xff09;创建 MDP 环境 创建一个具有 8 个状态和 2 …