这是2022版王道数据结构的第6章——图的算法大题的C语言代码实现,书上的练习题主要针对图的遍历且题目数量很少。代码都经过了简单的测试,基本上不会有太大问题。
编译环境为gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
,文件目录结构如下:
ch6
├── 6-3-graph_traversal.c
├── 6-3-graph_traversal_test.c
├── graph_adjacency_list.h
├── graph_adjacency_matrix.h
├── main
├── queue_link.h
└── stack_link.h
题目描述:
代码实现:
#include "graph_adjacency_list.h"
#include "graph_adjacency_matrix.h"
#include "queue_link.h"
#include "stack_link.h"
//2-判断一个无向图是否是一棵树
void DFS_count(MGraph graph, int v, int* vNum, int* eNum, bool* visited) {
visited[v] = true;
(*vNum)++;
for (Vertex i = 0; i < graph->Nv; ++i) {
if ((graph->g[v][i] != 0) && (graph->g[v][i] < INFINITY)) {
(*eNum)++;
if (!visited[i]) {
DFS_count(graph, i, vNum, eNum, visited);
}
}
}
}
bool isTree(MGraph graph) {
bool* visited = (bool*)malloc(sizeof(bool) * graph->Nv);
for (int i = 0; i < graph->Nv; ++i) {
visited[i] = false;
}
int vNum = 0;
int eNum = 0;
DFS_count(graph, 0, &vNum, &eNum, visited);
//printf("\nvNum=%d,eNum=%d\n", vNum, eNum);
free(visited);
return (vNum == graph->Nv) && (eNum == 2 * (graph->Nv - 1));
}
//3-DFS的非递归算法
//这是书上给的,就是把BFS的队列换成了栈,我觉得不对
void DFS_iteratively_1(LGraph graph, Vertex v) {
bool* visited = (bool*)malloc(sizeof(bool) * graph->Nv);
for (int i = 0; i < graph->Nv; ++i) {
visited[i] = false;
}
Stack s = CreateStack();
Vertex k;
printf("%3d ", v);
visited[v] = true;
Push(s, v);
while (!StackEmpty(s)) {
Pop(s, &k);
visited[k] = true;
for (PtrToAdjVNode p = graph->g[k].firstEdge; p != NULL; p = p->next) {
if (!visited[p->AdjV]) {
printf("%3d ", p->AdjV);
visited[p->AdjV] = true;
Push(s, p->AdjV);
}
}
}
DestoryStack(s);
free(visited);
}
//我觉得这是正确的DFS非递归
void DFS_iteratively_2(LGraph graph, Vertex v) {
bool* visited = (bool*)malloc(sizeof(bool) * graph->Nv);
for (int i = 0; i < graph->Nv; ++i) {
visited[i] = false;
}
Stack s = CreateStack();
Vertex k;
printf("%3d ", v);
visited[v] = true;
Push(s, v);
PtrToAdjVNode p = NULL;
while (!StackEmpty(s)) {
Top(s, &k);
for (p = graph->g[k].firstEdge; p != NULL; p = p->next) {
if (!visited[p->AdjV]) {
printf("%3d ", p->AdjV);
visited[p->AdjV] = true;
Push(s, p->AdjV);
break;
}
}
if (p == NULL) {
Pop(s, &k);
}
}
DestoryStack(s);
free(visited);
}
//4-分别基于dfs和bfs判别有向图中是否存在由i到j的路径
void reachable_DFS(LGraph g, Vertex i, Vertex j, bool* visited, bool* reachable) {
if (i == j) {
*reachable = true;
return;
} else {
visited[i] = true;
for (PtrToAdjVNode p = g->g[i].firstEdge; p != NULL; p = p->next) {
if (!visited[p->AdjV] && !(*reachable)) {
reachable_DFS(g, p->AdjV, j, visited, reachable);
}
}
}
}
void reachable_BFS(LGraph g, Vertex i, Vertex j, bool* visited, bool* reachable) {
Queue q = CreateQueue();
EnQueue(q, i);
visited[i] = true;
Vertex v;
while (!QueueEmpty(q)) {
DeQueue(q, &v);
if (v == j) {
*reachable = true;
return;
}
for (PtrToAdjVNode p = g->g[v].firstEdge; p != NULL; p = p->next) {
if (p->AdjV == j) {
*reachable = true;
return;
}
if (!visited[p->AdjV]) {
EnQueue(q, p->AdjV);
visited[p->AdjV] = true;
}
}
}
DestoryQueue(q);
}
//5-输出从i到j的所有简单路径
void findPath(LGraph g, Vertex i, Vertex j, Vertex* path, int d, bool* visited) {
d++;
path[d] = i;
visited[i] = true;
if (i == j) {
for (int k = 0; k <= d; ++k) {
printf("%2d ", path[k]);
}
printf("\n\n");
}
for (PtrToAdjVNode p = g->g[i].firstEdge; p != NULL; p = p->next) {
if (!visited[p->AdjV]) {
findPath(g, p->AdjV, j, path, d, visited);
}
}
visited[i] = false;
}
测试代码:
#include "6-3-graph_traversal.c"
#include
#include
#include
void test_isTree() {
printf("\n%s\n", __func__);
WeightType m[5][5] = {
{0, 1, 1, 1, INFINITY},
{1, 0, INFINITY, INFINITY, 1},
{1, INFINITY, 0, INFINITY, INFINITY},
{1, INFINITY, INFINITY, 0, INFINITY},
{INFINITY, 1, INFINITY, INFINITY, 0}};
MGraph g = CreateMGraphFromMatrix(&m[0][0], NULL, 5, false);
//PrintMGraph(g);
bool result;
result = isTree(g);
printf("\nresult=%d\n", result);
//now,他不是一棵树了
g->g[2][4] = 1;
result = isTree(g);
printf("\nresult=%d\n", result);
DestoryMGraph(g);
}
void test_DFS_iteratively_1() {
printf("\n%s\n", __func__);
WeightType m[5][5] = {
{0, 1, 1, 1, INFINITY},
{1, 0, INFINITY, INFINITY, 1},
{1, INFINITY, 0, 1, 1},
{1, INFINITY, 1, 0, INFINITY},
{INFINITY, 1, 1, INFINITY, 0}};
LGraph g = CreateLGraphFromMatrix(&m[0][0], NULL, 5, false);
PrintLGraph(g);
printf("\n");
DFS_iteratively_1(g, 0);
printf("\n");
DestoryLGraph(g);
}
void test_DFS_iteratively_2() {
printf("\n%s\n", __func__);
WeightType m[5][5] = {
{0, 1, 1, 1, INFINITY},
{1, 0, INFINITY, INFINITY, 1},
{1, INFINITY, 0, 1, 1},
{1, INFINITY, 1, 0, INFINITY},
{INFINITY, 1, 1, INFINITY, 0}};
LGraph g = CreateLGraphFromMatrix(&m[0][0], NULL, 5, false);
PrintLGraph(g);
printf("\n");
DFS_iteratively_2(g, 0);
printf("\n");
DestoryLGraph(g);
}
void test_reachable_DFS_BFS() {
printf("\n%s\n", __func__);
WeightType m[5][5];
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
if (i == j) {
m[i][j] = 0;
} else {
m[i][j] = INFINITY;
}
}
}
m[0][1] = 1;
m[0][2] = 1;
m[0][3] = 1;
m[3][4] = 1;
LGraph g = CreateLGraphFromMatrix(&m[0][0], NULL, 5, true);
bool* visited = (bool*)malloc(sizeof(bool) * g->Nv);
memset(visited, 0, 5 * sizeof(bool));
bool result = false;
PrintLGraph(g);
int i, j;
i = 0;
j = 4;
reachable_DFS(g, i, j, visited, &result);
printf("\ni=%d,j=%d,result=%d\n", i, j, result);
memset(visited, 0, 5 * sizeof(bool));
result = false;
reachable_BFS(g, i, j, visited, &result);
printf("\ni=%d,j=%d,result=%d\n", i, j, result);
memset(visited, 0, 5 * sizeof(bool));
result = false;
i = 4;
j = 0;
reachable_DFS(g, i, j, visited, &result);
printf("\ni=%d,j=%d,result=%d\n", i, j, result);
memset(visited, 0, 5 * sizeof(bool));
result = false;
reachable_BFS(g, i, j, visited, &result);
printf("\ni=%d,j=%d,result=%d\n", i, j, result);
memset(visited, 0, 5 * sizeof(bool));
result = false;
i = 2;
j = 4;
reachable_DFS(g, i, j, visited, &result);
printf("\ni=%d,j=%d,result=%d\n", i, j, result);
memset(visited, 0, 5 * sizeof(bool));
result = false;
reachable_BFS(g, i, j, visited, &result);
printf("\ni=%d,j=%d,result=%d\n", i, j, result);
memset(visited, 0, 5 * sizeof(bool));
result = false;
i = 3;
j = 4;
reachable_DFS(g, i, j, visited, &result);
printf("\ni=%d,j=%d,result=%d\n", i, j, result);
memset(visited, 0, 5 * sizeof(bool));
result = false;
reachable_BFS(g, i, j, visited, &result);
printf("\ni=%d,j=%d,result=%d\n", i, j, result);
memset(visited, 0, 5 * sizeof(bool));
result = false;
DestoryLGraph(g);
free(visited);
}
void test_findPath() {
printf("\n%s\n", __func__);
WeightType m[5][5];
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
if (i == j) {
m[i][j] = 0;
} else {
m[i][j] = INFINITY;
}
}
}
m[0][1] = 1;
m[0][2] = 1;
m[0][3] = 1;
m[3][4] = 1;
LGraph g = CreateLGraphFromMatrix(&m[0][0], NULL, 5, true);
bool* visited = (bool*)malloc(sizeof(bool) * g->Nv);
memset(visited, 0, 5 * sizeof(bool));
PrintLGraph(g);
int i, j;
int d = -1;
int* path = (int*)malloc(sizeof(int) * 5);
memset(path, -1, sizeof(int) * 5);
i = 0;
j = 4;
findPath(g, i, j, path, d, visited);
DestoryLGraph(g);
free(visited);
free(path);
}
int main(int argc, char* argv[]) {
#if 1
test_isTree();
test_DFS_iteratively_1();
test_DFS_iteratively_2();
test_reachable_DFS_BFS();
#endif
test_findPath();
return 0;
}