2022版王道数据结构算法题C语言代码实现-第6章-图

概述

这是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

图的遍历

题目描述:

2022版王道数据结构算法题C语言代码实现-第6章-图_第1张图片

代码实现:

#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;
}

你可能感兴趣的:(数据结构与算法,算法,数据结构,c语言,图论)