首页 > 其他分享 >图的几种存储方法

图的几种存储方法

时间:2022-09-01 08:25:18浏览次数:62  
标签:200 存储 return int adj cnt 几种 vis 方法

作为我们学习图论的基点,我们有必要了解几种常用的图存储方法,并比较他们的优劣与适用范围。

本文参考了https://oi-wiki.org/graph/save/

直接存边:

由于直接存边的遍历效率低下,一般不用于遍历图。

在 Kruskal算法中,由于需要将边按边权排序,需要直接存边。

在有的题目中,需要多次建图(如建一遍原图,建一遍反图),此时既可以使用多个其它数据结构来同时存储多张图,也可以将边直接存下来,需要重新建图时利用直接存下的边来建图。

 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4 int pos1=0;//绝对位置 
 5 int tire[100][30];
 6 int end[100];//储存是否为末尾 
 7 void insert (string s){
 8     int start=0;
 9     for (int i=0;i<s.length();i++){
10         int pos2=s[i]-'a';
11         if (!tire[start][pos2]){
12             tire[start][pos2]=++pos1;
13         }
14         start=pos1;
15     }
16     end[start]=1;//给末尾标记上 
17 }
18 bool find(string s){
19     int start=0;
20     for (int i=0;i<s.length();i++){
21         int pos2=s[i]-'a';
22         if (!tire[start][pos2])
23             return false;
24         start=tire[start][pos2];
25     }
26     return end[start];//查找末尾是否有标记 
27 }
28 int main(){
29     insert("ans");
30     cout<<find("ansser")<<find("ans")<<find("an");
31     return 0;
32 }

 邻接矩阵存储:

邻接矩阵只适用于没有重边(或重边可以忽略)的情况。

其最显著的优点是可以 O(1)查询一条边是否存在。

由于邻接矩阵在稀疏图上效率很低(尤其是在点数较多的图上,空间无法承受),所以一般只会在稠密图上使用邻接矩阵。

代码如下:

 1 #include <iostream>
 2 using namespace std;
 3 int adj[200][200];
 4 int vis[200];
 5 int k;//顶点数
 6 int n;//边数 
 7 void insert (int u,int v,int w){
 8     adj[u][v]=w;
 9     adj[v][u]=w;//无向图需要存两条,有向图存一条即可 
10 }
11 bool find_root(int u,int v){
12     return adj[u][v];
13 }
14 void dfs(int u){
15     if (vis[u]) return ;
16     vis[u]=true;
17     cout<<u<<" ";
18     for (int i=1;i<=k;i++){
19         if (adj[u][i])
20             dfs(i);
21     }
22 }
23 int main(){
24     cin>>k>>n;
25     for (int i=1;i<=n;i++){
26         int u,v;
27         cin>>u>>v;
28         insert(u,v,1);
29     }
30     dfs(1);
31     return 0;
32 }

邻接表存储:

存各种图都很适合,除非有特殊需求(如需要快速查询一条边是否存在,且点数较少,可以使用邻接矩阵)。

尤其适用于需要对一个点的所有出边进行排序的场合。

 1 #include <iostream>
 2 #include <vector>
 3 using namespace std;
 4 vector<vector<int> >adj;
 5 int k;//点数 
 6 int n;//边数 
 7 int vis[200];
 8 bool find_root(int u,int v){
 9     for (int i=0;i<adj[u].size();i++){
10         if (adj[u][i]==v)
11             return true;
12     }
13     return false;
14 }
15 void dfs(int u){
16     if (vis[u]) return ;
17     vis[u]=true;
18     cout<<u<<" ";
19     for (int i=0;i<adj[u].size();i++){
20         dfs(adj[u][i]);
21     }
22 }
23 int main(){
24     cin>>k>>n;
25     adj.resize(k+1);//初始化
26     for (int i=1;i<=n;i++){
27         int u,v;
28         cin>>u>>v;
29         adj[u].push_back(v);
30     }
31     dfs(1);
32     return 0;
33 }

链式前向星:

存各种图都很适合,但不能快速查询一条边是否存在,也不能方便地对一个点的出边进行排序。

优点是边是带编号的,有时会非常有用,而且如果 cnt 的初始值为奇数,存双向边时 i ^ 1 即是 i 的反边(常用于网络流)。

 1 #include <iostream>
 2 using namespace std;
 3 int cnt=0;//边的标号
 4 int nxt[200];//储存和本条边同出发点的上一条边
 5 int head[200];//储存开始节点标号为i的最新边
 6 int to[200];//储存标号为i的边的终止点
 7 int w[200];//储存标号为i的边的权重 
 8 int k;//点数 
 9 int n;//边数 
10 int vis[200];
11 void insert(int u,int v,int w1){
12     nxt[++cnt]=head[u];
13     head[u]=cnt;
14     to[cnt]=v;
15     w[cnt]=w1;
16 }
17 bool find_root(int u,int v){
18     for (int i=head[u];i;i=nxt[i]){
19         if (to[i]==v)
20             return true;
21     }
22     return false;
23 }
24 void dfs(int u){
25     if (vis[u]) return ;
26     vis[u]=true;
27     cout<<u<<" ";
28     for (int i=head[u];i;i=nxt[i]){
29         dfs(to[i]);
30     }
31 }
32 int main(){
33     cin>>k>>n;
34     for (int i=1;i<=n;i++){
35         int u,v;
36         cin>>u>>v;
37         insert(u,v,1);
38         insert(v,u,1);//无向图存两次 
39     }
40     dfs(1);
41     return 0;
42 }

 

标签:200,存储,return,int,adj,cnt,几种,vis,方法
From: https://www.cnblogs.com/johnsonstar/p/16645091.html

相关文章

  • System.getProperty方法
    DemoprivatestaticStringzookeeperHost=System.getProperty("zookeeper.address","127.0.0.1");privatestaticStringzookeeperPort=System.getProperty("zoo......
  • 高级开发人员知识:JavaScript 数组方法第 3 部分
    高级开发人员知识:JavaScript数组方法第3部分今天让我们来点高级的。这些数组方法总是遍历数组。基本上,您可以通过基本的for循环获得相同的功能。如果是这样,我们为什......
  • 在 Nodejs 中从终端获取用户输入的 4 种方法。
    在Nodejs中从终端获取用户输入的4种方法。当我们开始学习任何编程语言时,我们希望从终端获取用户输入。大多数人从c、c++、java等语言开始他们的编程之旅。在这些语......
  • jdk8新特性之方法引用和日期
    方法引用的三种表现形式方法引用的基本思想是,如果一个Lambda代表的只是“直接调用这个方法”,那最好还是用名称来调用它,而不是去描述如何调用它。事实上,方法引用就是让你......
  • 静态文件、请求方法、request对象、连接数据库、ORM
    目录静态文件及相关配置一、编写登录功能二、访问资源三、静态文件1.定义:2.位置:3.static文件夹:4.针对静态文件资源的访问也需要提前开设相应的接口5.接口前缀6.动态解析请......
  • request对象方法与django连接MySQL
    静态文件配置1.编写一个登录功能1.1创建django项目并创建一个app1.2在urls.py添加一组对应关系urlpatterns=[path('admin/',admin.site.urls),path('log......
  • 本地存储特性
    1、本地存储特性①、数据存储在用户浏览器中;②、设置、读取方便、甚至页面刷新不丢失数据;③、容量较大,sessionStorage约5M,localStorage约20M;④、只能存储字符串,可以将......
  • 0Java切分字符串的几种方式
    Java切分字符串的几种方式java分割字符串,匹配多种分隔符......
  • CentOS yum 段错误 (core dumped)解决方法
    CentOSyum段错误(coredumped)解决方法_RedHat/Centos_操作系统_脚本之家 https://www.jb51.net/os/RedHat/208481.html今天在yuminstall或者yumupdate的时候都提......
  • Python根据类中属性自定义排序的方法
    如果以创建的对象作为列表中的元素,那么对列表进行排序时可使用sort()函数或sorted()函数,但要注意的是:①当排序对象为列表的时候两者适合的场景不同②sorted()函数会返......