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.mzph.cn/news/740130.shtml

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

相关文章

Vue3全家桶 - Vue3 - 【4】侦听器

侦听器 一、 组合式API&#xff1a; 1.1 watch()函数 创建侦听器: 语法:// 先导入 watch 函数 import { watch } from vue watch(source, callback, options)source&#xff1a; 需要侦听的数据源&#xff0c;可以是 ref&#xff08;包括计算属性&#xff09;、一个响应式对…

Linux内核介绍and下载

Linux内核介绍and下载 介绍下载下载历史版本 我是将军我一直都在&#xff0c;。&#xff01; 介绍 ● Linux是c语言写成的 ● 符合POSIX标准 ● 作者是芬兰的Linus Torvalds ● 发展依赖于五个重要支柱: unix操作系统、minix操作系统、 GNU计划、POSIX标准和互联网 ● 2.6之后…

打卡--MySQL8.0 二 (用户权限管理)

一、mysql8修改了安全规则&#xff0c;不能像mysql5.7 一次性创建用户并授权&#xff0c;需要分批创建。 1、注意在MySQL8.0版本中创建用户一定要在配置文件中增加如下内容&#xff0c;来兼容旧的程序运行。 default_authentication_pluginmysql_native_password 2、创建用户…

全景解析 Partisia Blockchain:以用户为中心的全新数字经济网络

在区块链世界中&#xff0c;以比特币、以太坊网络为代表的主流区块链奠定了该领域早期的基础&#xff0c;并让去中心化、点对点、公开透明以及不可逆成为了该领域固有的意识形态。事实上&#xff0c;过于透明正在成为区块链规模性采用的一大障碍&#xff0c;我们看到 90% 以上的…

【Attribute】Inspector视图枚举字段范围限定特性

简介 为了提升枚举的复用性&#xff0c;有时候我们可以通过限定枚举字段的范围来避免定义新的枚举类型&#xff0c;例如有一个代表方向的枚举&#xff08;包括None&#xff0c;Left&#xff0c;Up&#xff0c;Right&#xff0c;Down&#xff09;&#xff0c;全局方向&#xff0…

ThreeWayBranch 优化阅读笔记

1. 优化目的 通过重排三分支的 BB 块减少比较指令的执行次数 代码路径: bolt/lib/Passes/ThreeWayBranch.cpp2. 效果 优化前&#xff1a; 注&#xff1a; 黄色数字表示BB块编号&#xff0c; 紫色表示该分支跳转的次数&#xff0c;绿色是代码里BB块的变量名 ThreeWayBranc…

精读《React Conf 2019 - Day2》

1 引言 这是继 精读《React Conf 2019 - Day1》 之后的第二篇&#xff0c;补充了 React Conf 2019 第二天的内容。 2 概述 & 精读 第二天的内容更为精彩&#xff0c;笔者会重点介绍比较干货的部分。 Fast refresh Fast refresh 是更好的 react-hot-loader 替代方案&am…

Spring Cloud Alibaba微服务从入门到进阶(二)

Spring Boot配置管理 1、application.properties 2、application.yml 1.内容格式比较&#xff1a; .properties文件&#xff0c;通过 . 来连接&#xff0c;通过 来赋值&#xff0c;结构上&#xff0c;没有分层的感觉&#xff0c;但比较直接。 .yml文件&#xff0c;通过 &…

Jade 处理XRD并计算半峰宽FWHM、峰面积、峰强度等数据

1.打开软件 2.导入测试的XRD数据 3.平滑数据 4.抠一下基底 5.分析具体数据 6.按住鼠标左键&#xff0c;在峰底部拉一条线&#xff0c;尽量和基底持平 7.结果就出来了&#xff0c;想要的都在里面&#xff0c;直接取值就行

初级爬虫实战——伯克利新闻

文章目录 发现宝藏一、 目标二、简单分析网页1. 寻找所有新闻2. 分析模块、版面和文章 三、爬取新闻1. 爬取模块2. 爬取版面3. 爬取文章 四、完整代码五、效果展示 发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不…

Linux命令深入学习——列出帮助手册,开机关机

linux中有多种方法查看一个不熟悉命令的详细信息&#xff0c;如 ls --help&#xff0c;help ls&#xff0c;man ls&#xff0c;info ls 在linux系统中可以使用命令进行开关机以及相关基础操作 同时在进行写入操作时&#xff0c;可以使用快捷键进行操作

Linux文件与文件系统的压缩

文章目录 Linux文件与文件系统的压缩Linux系统常见的压缩命令gzip&#xff0c;zcat/zmore/zless/zgrepbzip2&#xff0c;bzcat/bzmore/bzless/bzgreppxz&#xff0c;xzcat/xzmore/xzless/xzgrepgzip&#xff0c;bzip2&#xff0c;xz压缩时间对比打包命令&#xff1a;tar打包命令…

马斯克放出豪言,他旗下的xAI要把Grok开源了

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Halcon 使用光流算子检测运动物体

文章目录 算子optical_flow_mg 计算两个图像之间的光流vector_field_length 计算向量场的向量长度select_shape_std 选择给定形状的区域vector_field_to_real 将矢量场图像转换为两个实值图像intensity 计算灰度值的均值和偏差local_max_sub_pix 以亚像素精度检测局部极大值 Ha…

LVS负载均衡群集之NAT与DR模式

一 集群和分布式 企业群集应用概述 群集的含义 Cluster&#xff0c;集群、群集 由多台主机构成&#xff0c;但对外只表现为一个整体&#xff0c;只提供一个访问入口(域名或IP地址)&#xff0c;相当于一台大型计算机。 问题&#xff1f; 互联网应用中&#xff0c;随着站点对…

JVM优化

Java编码执行流程图 a.java ->javac&#xff08;前端编译器&#xff0c;javac属于其中一种&#xff09; ->a.class 和java类库 ->classloader-> Java解释器(一行行解释并运行) 或即时编译器JIT(Just In Time&#xff0c;属于后端编译器)JIT可以将一个方法&#xff…

SpringBoot多数据源切换 多数据源事务解决方案 二

https://zhuanlan.zhihu.com/p/612825647?utm_id0 https://blog.csdn.net/guzhangyu12345/article/details/108559810 SpringBoot多数据源事务解决方案 https://blog.csdn.net/u013407099/article/details/124526396多数据源切换下保证事务解决方案 https://blog.csdn.net/re…

郑州大学2024年3月acm实验室招新赛题解(A-L)

这里感谢一下计算机学术交流协会会长&#xff0c;acm实验室的中坚成员&#xff0c;以及本次比赛的出题人之一孙昱涵将他的账号借给了我。 回顾一下的话&#xff0c;这场的难度其实不是很大&#xff0c;不过对招新的新手来说难度还是挺大的。去掉签到都没签出来的选手的话&…

【C++ Primer Plus学习记录】第6章复习题

1.请看下面两个计算空格和换行符数目的代码片段&#xff1a; //Version 1 while(cin.get(ch)) //quit on eof,EOF(检测文件尾) { if(ch )spaces;if(ch \n)newlines; }//Version 2 while(cin.get(ch)) //quit on eof { if(ch )spaces;else if(ch \n)newlines; } 第…

C++_异常

目录 1、异常的关键字 2、异常的写法 3、异常的使用规则 3.1 规则1 3.2 规则2 3.3 规则3 3.4 规则4 3.5 规则5 4、异常的重新抛出 5、异常的规范 5.1 C98的异常规范 5.2 C11的异常规范 6、C标准库的异常体系 7、异常的优缺点 结语 前言&#xff1a; C的异常…