图的基本储存方式
邻接矩阵
邻接矩阵储存图的方法,顾名思义,就是用二维数组来存数。
下面看具体存储方法:
(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
以上就是全部内容,本篇博客是自己对图的学习总结,欢迎各位大佬们指点~