图的基本储存方式

邻接矩阵

邻接矩阵储存图的方法,顾名思义,就是用二维数组来存数。
下面看具体存储方法:
(1)无向边
这是一个无向图,由5个结点,6条边组成,1和2有边,1和3有边,1和5有边,3和4有边,4和5有边,2和4有边。好了,图的基本信息介绍完了,下面废话不多说直接上二维数组,解释邻接矩阵。在这里插入图片描述这是以主对角线对称的二维数组,因为是无向边,所以顾名思义,很容易懂。这里就不细说了。把有边的地方变成1,没边的地方是0。
(2)有向图,有向图和无向图类似,找对应关系即可,这里不多说。
下面上代码。


#include <string.h>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
bool map[5005][5005];//map数组记录边的情况,bool函数返回值只有两种true(1)和false(0)节省了空间。
int main() {
    ios::sync_with_stdio(false);//这个可以自己上网查,可以大大提升cin,cout的速度。
     int n,m,u,v,q;
     while(cin>>n>>m)
     { 
          memset(map,0,sizeof(map));
          while(m--)
          {
              cin>>u>>v;
              map[u][v]=true;
          }
          cin>>q;
          while(q--)
          {
              cin>>u>>v;
              if(map[u][v])
              {
                  cout<<"Yes"<<endl;
              }
              else cout<<"No"<<endl;
          }
     }
    return 0;
}

题目链接: 邻接矩阵题目.

邻接表

邻接表和链表无异,是一种顺序分配和链式分配相结合的存储结构。如这个表头结点所对应的顶点存在相邻顶点,则把相邻顶点依次存放于表头结点所指向的单向链表中。图的邻接表储存方式相对于邻接矩阵比较节约空间,对于邻接矩阵需要分别把顶点和边(顶点之间的关系)用一维数组和二维数组储存起来。而邻接表则是把顶点按照顺序储存到一维数组中,然后再通过链式方式,把有关系的顶点下标链接到后方。
下面以有向图为例:
在这里插入图片描述这个有向图就不介绍了,直接看分析。
在这里插入图片描述每一个链节都有一个数据域和一个指针域,数据域用来存图里的末节点数值(指箭头所指的那个,为了方便说明)这样既节省空间又简单明了。
下面看代码实现:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;
struct node {
    int v;
    node *next;
} * arr[5005], *p;//结构体构建链
void add(int u, int v) {  //插入节点函数
    p = new node;//申请空间
    if (arr[u] == NULL) {
        p->v = v;
        p->next = NULL;
        arr[u] = p;
    } else {
        p->v = v;
        p->next = arr[u]->next;从最前面插入,类似逆序建链表
        arr[u]->next = p;
    }
}
bool query(int u, int v) {
   node *a = arr[u];
    while (a) {
        if (a->v == v) {
            return true;
        }
        a = a->next;
    }
    return false;
}
int main() {
    ios ::sync_with_stdio(false);
    int n, m, u, v, q;
    while (cin >> n) {
        memset(arr, 0, sizeof(arr));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                cin >> u;
                if (u) {
                    add(i, j);
                }
            }
        }
        cin >> q;
        while (q--) {
            cin >> u >> v;
            if (query(u, v)) {
                cout << "Yes\n";
            } else {
                cout << "No\n";
            }
        }
    }
    return 0;
}

题目链接: 邻接表题目.

链式前向星

链式前向星继承了,邻接表的优点,在其基础上也进行了改进,不采用指针的方式建链表,操作方法和邻接表类似,示意图可以看上面的图片。
推荐一个前向星讲解视频。
链接: 链式前向星讲解视频
下面看代码实现:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
struct node{
    int data;
    int next;
}edge[500005];
int cnt = 0;
int head[500005];
void add(int u,int v){
    edge[cnt].data = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}
bool query(int u,int v){
    for(int i = head[u];i!=-1;i = edge[i].next){
        if(edge[i].data==v){
            return true;
        }
    }
    return false;
}
int main() {
    ios :: sync_with_stdio(false);
    int n,m,u,v,q;
    while(cin>>n>>m) {
        memset(head,-1,sizeof(head));
        while(m--){
            cin>>u>>v;
            add(u,v);
        }
        cin>>q;
        while(q--){
            cin>>u>>v;
            if(query(u,v)){
                cout<<"Yes\n";
            }else{
                cout<<"No\n";
            }
        }
    }
    return 0;
}

链接: 链式前向星题目.

邻接表vector改进算法

邻接表vector改进是c++的一个方法,优点就是简单,方便,快捷,不用自己写具体代码操作。
a[u].push_back(v) 代表插入一个节点,数据域的值是末节点的值。
a[u].size() 代表a[u]后面所接链表的长度
下面看代码实现:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

int main() {
    ios ::sync_with_stdio(false);
    int n, m, u, v, q;
    while (cin >> n >> m) {
        vector<int> a[500005];
        while (m--) {
            cin >> u >> v;
            a[u].push_back(v);
        }
        cin >> q;
        while (q--) {
            cin >> u >> v;
            int flag = 0;
            for (int i = 0; i < a[u].size(); i++) {
                if (a[u][i] == v) {
                    flag = 1;
                    break;
                }
            }
            if (flag) {
                cout << "Yes\n";
            } else {
                cout << "No\n";
            }
        }
    }
    return 0;
}

参考博客:https://blog.csdn.net/rwbyblake/article/details/106281836

以上就是全部内容,本篇博客是自己对图的学习总结,欢迎各位大佬们指点~

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值