by.Qin3Yu
请注意:严格来说,图不是一种数据结构,而是一种抽象数据类型。但为了保证知识点之间的相关性,也将其列入数据结构专栏。
本文需要读者掌握顺序表和单链表的操作基础,若需学习,可参阅我的往期文章:
【C++数据结构 | 顺序表速通】使用顺序表完成简单的成绩管理系统.by.Qin3Yu
【C++数据结构 | 单链表速通】使用单链表完成数据的输入和返回元素之和.by.Qin3Yu
本文将不会涉及图的具体操作案例,若需阅读案例,可参阅我的往期文章:
【经典案例 | 骑士之旅】回溯算法解决经典国际象棋骑士之旅问题 | 详解Knight’s Tour Problem数学问题.by.Qin3Yu
【算法详解 | 最小生成树 I 】详解最小生成树prim算法(拓展kruskal算法) | 电力网络最短路径覆盖问题.by.Qin3Yu
文中所有代码默认已使用std命名空间且已导入部分头文件:
#include
#include
using namespace std;
特别注意:有向图需双向连通才算作强连通图!
一个明确的图应具有以下特征:
1. 无重复边: 在无向图中,每对点之间只有唯一的一条边连接,不存在一对点之间有两条边的情况;
2. 明确向性: 大多数情况下的图要么是有向图,要么是无向图,很少存在同一张图中某些边有向同时某些边无相(混合图)的情况;
3. 无自环: 在图中不存在连接一个节点到其自身的边。
图根据稀疏和稠密的特征有两种常用的存储方式,分别是邻接矩阵和邻接表。
int n = 6; // 点数
vector<vector<int>> Graph(n, vector<int>(n, 0)); // 初始化一个n×n的矩阵,默认为0
for (int i = 0; i < n; i++) {
int x, y;
cin >> x >> y;
Graph[x][y] = 1;
Graph[y][x] = 1; // 对称输入
}
int m = ... // 边数
for (int i = 0; i < m; i++) {
int x, y;
cin >> x >> y;
Graph[x][y] = 1;
}
//定义单链表
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
const int n = 6; // 节点数
const int m = 7; // 边数
ListNode* Graph[n]; // 声明多个链表
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
ListNode* newNode = new ListNode(v);
newNode->next = Graph[u];
Graph[u] = newNode;
}
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
ListNode* newNode1 = new ListNode(v);
newNode1->next = Graph[u];
Graph[u] = newNode1;
ListNode* newNode2 = new ListNode(u);
newNode2->next = Graph[v];
Graph[v] = newNode2;
}
代码
#include
#include
using namespace std;
int n = 6; // 点数
int m = 7; // 边数
vector<vector<int>> Graph(n, vector<int>(n, 0));
int main() {
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
Graph[u][v] = 1;
Graph[v][u] = 1;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
cout << Graph[i][j] << " ";
cout << endl;
}
return 0;
}
参考输入
0 1
1 2
2 3
3 4
4 0
2 5
3 5
参考输出
0 1 0 0 1 0
1 0 1 0 0 0
0 1 0 1 0 1
0 0 1 0 1 1
1 0 0 1 0 0
0 0 1 1 0 0
代码
#include
#include
using namespace std;
int n = 6; // 点数
int m = 7; // 边数
vector<vector<int>> Graph(n, vector<int>(n, 0));
int main() {
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
Graph[u][v] = 1;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
cout << Graph[i][j] << " ";
cout << endl;
}
return 0;
}
参考输入
0 1
1 2
2 3
3 4
4 0
3 5
5 3
参考输出
0 1 0 0 0 0
0 0 1 0 0 0
0 0 0 1 0 0
0 0 0 0 1 1
1 0 0 0 0 0
0 0 0 1 0 0
代码
#include
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
const int n = 6; // 节点数
const int m = 7; // 边数
ListNode* Graph[n];
int main() {
for (int i = 0; i < n; i++)
Graph[i] = nullptr;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
ListNode* newNode1 = new ListNode(v);
newNode1->next = Graph[u];
Graph[u] = newNode1;
ListNode* newNode2 = new ListNode(u);
newNode2->next = Graph[v];
Graph[v] = newNode2;
}
for (int i = 0; i < n; i++) {
cout << i << ": ";
ListNode* curr = Graph[i];
while (curr != nullptr) {
cout << curr->val << " ";
curr = curr->next;
}
cout << endl;
}
return 0;
}
参考输入
0 1
1 2
2 3
3 4
4 0
2 5
3 5
参考输出
0: 4 1
1: 2 0
2: 5 3 1
3: 5 4 2
4: 0 3
5: 3 2
代码
#include
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
const int n = 6; // 节点数
const int m = 7; // 边数
ListNode* Graph[n];
int main() {
for (int i = 0; i < n; i++)
Graph[i] = nullptr;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
ListNode* newNode = new ListNode(v);
newNode->next = Graph[u];
Graph[u] = newNode;
}
for (int i = 0; i < n; i++) {
cout << i << ": ";
ListNode* curr = Graph[i];
while (curr != nullptr) {
cout << curr->val << " ";
curr = curr->next;
}
cout << endl;
}
return 0;
}
参考输入
0 1
1 2
2 3
3 4
4 0
3 5
5 3
参考输出
0: 1
1: 2
2: 3
3: 5 4
4: 0
5: 3
by.Qin3Yu