• 邻接表转化为逆邻接表


    题目描述:

    已知有n个顶点的有向图G的邻接表,设计算法求邻接表G的逆邻接表。

    思路:

    将邻接表转化为逆邻接表需要遍历所有邻接表的整个顶点表G,然后便可得到每个顶点有哪些顶点指向它,然后将其信息放入逆邻接表GIn中(由邻接表可以得到所有顶点的出度,逆邻接表则得到的是入度)

    我们首先以下图这个有向图为例子,得到一个输入样例:

    请添加图片描述

    6 8
    1 2
    1 4
    4 2
    2 5
    5 4
    3 5
    3 6
    6 6
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    样例输出如下:
    在这里插入图片描述

    (先上代码)

    #include
    using namespace std;
    const int MaxVeertexNum = 100; // 图中顶点数目的最大值
    typedef struct ArcNode { //边表结点
        int adjvex; // 该弧所指向的顶点的位置
        struct ArcNode *next; //指向下一条弧的指针
        // int weight; //网的边权值
        // Infotype info;
    }ArcNode;
    typedef struct VNode { //顶点表结点
        int data; //顶点信息 (VertexType data;)
        ArcNode *first; // 指向第一条依附该顶点的弧的指针
    }VNode, AdjList[MaxVeertexNum];
    typedef struct {
        AdjList vertices; //邻接表
        int vernum, arcnum; //图的顶点数和弧数
    }ALGraph; // ALGraph是以邻接表存储的图类型
    void Create_AdjList_Graph(ALGraph &G) { //创建一个邻接表
        scanf("%d%d", &G.vernum, &G.arcnum); //输入图的顶点数和边数
        for(int i = 1; i <= G.vernum; i++) {
            G.vertices[i].data = i; //假设顶点信息是1....vernum
            G.vertices[i].first = NULL; //初始化第一条依附该顶点的弧的指针为空
        }
        ArcNode *p;
        for(int i = 0; i < G.arcnum; i++) {
            int u, v;
            scanf("%d%d", &u, &v); //u, v表示u有一条边指向v;
            p = (ArcNode *) malloc (sizeof(ArcNode)); // p = new ArcNode;
            p -> adjvex = v;
            p -> next = G.vertices[u].first; //用头插法将v插到结点u的边表结点中
            G.vertices[u].first = p; // 插入后将第一条依附该顶点的弧的指针修改为p
        }
    }
    void adjacency_to_inverse_adjacency(ALGraph GOut, ALGraph &GIn) { 
        /*将图的邻接表转化为逆邻接表*/
        GIn.arcnum = GOut.arcnum; //初始化逆邻接表的边数目
        GIn.vernum = GOut.vernum; //初始化逆邻接表的顶点数目
        for (int i = 1; i <= GIn.vernum; i++) { 
            GIn.vertices[i].data = GOut.vertices[i].data; // 初始化逆邻接表的顶点信息
            GIn.vertices[i].first = NULL; // 初始化指向第一条依附该顶点的弧的指针
        }
        for(int i = 1; i <= GOut.vernum; i++) {
            ArcNode *p = GOut.vertices[i].first; // 取得指向第一条依附该顶点的弧的指针
            ArcNode *s;
            while(p != NULL) { // 遍历邻接表中第i个顶点所有邻接边 
                s = (ArcNode *) malloc (sizeof(ArcNode)); // or s = new ArcNode;
                int temp = p -> adjvex;
                s -> adjvex = i;
                s -> next = GIn.vertices[temp].first; //头插法将顶点i挂到GIn.vertices[temp]的边表中
                GIn.vertices[temp].first = s;
                p = p -> next; // 继续往后遍历i所指向的顶点
            }
        }
    }
    void print(ALGraph G) { // 打印邻接表
        for(int i = 1; i <= G.vernum; i++) {
            printf("(%d) ", i);
            ArcNode *p = G.vertices[i].first;
            while(p) {
                printf("-> %d ", p -> adjvex);
                p = p -> next;
            }
            puts("");
        }
    }
    int main() {
        ALGraph GraphOut, GraphIn; // GraphOut为邻接表,GraphIn为逆邻接表
        Create_AdjList_Graph(GraphOut); // 构造邻接表
        cout << endl;
        print(GraphOut); //打印邻接表
        adjacency_to_inverse_adjacency(GraphOut, GraphIn);
        cout << endl;
        print(GraphIn); //打印逆邻接表
        
        return 0;
    }
    /*
    测试样例二:
    9 14
    1 2
    1 3
    2 5
    2 4
    5 3
    5 4
    5 6
    6 5
    3 8
    8 9
    9 6
    4 7
    7 6
    7 9
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    小结:
    由于没有在各大oj上找到这么一道题可以测试自己代码的正确性,所以自己也就简单地测试了几组数据,如有不足的地方,欢迎大家指出来以及请大家见谅,指出来之后我会尽快修改。

  • 相关阅读:
    C++环境配置【学习笔记(一)】
    P6183 [USACO10MAR] The Rock Game S
    PaaS、 IaaS 和 SaaS 的区别
    [附源码]计算机毕业设计校园租赁系统Springboot程序
    【BOOST C++】高级01 RAII和内存管理
    windows如何更改/禁用系统更新
    busybox命令裁剪
    人力项目框架解析新增修改方法
    Zeus IoT : 基于 SpringBoot 的分布式开源物联网大数据平台
    Selenium实现批量将CSDN文章改为【粉丝可见】
  • 原文地址:https://blog.csdn.net/liupang14159/article/details/126301747