天空闲话 发表于 2024-8-15 20:00:53

《数据布局(C语言版)第二版》第六章-图(6.4 图的存储布局——6.4.2 毗邻

6.4.2 毗邻表

接纳毗邻表表现法创建无向图

//算法6.2 采用邻接表表示法创建无向图

#include <stdio.h>
#include <stdlib.h>

#define MVNum 100

typedef int OtherInfo;   //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType;//假设顶点的数据类型为字符型

typedef struct ArcNode
{
        int adjvex;
        struct ArcNode* nextarc;
        OtherInfo info;
}ArcNode;//边结点

typedef struct VNode
{
        VerTexType data;
        ArcNode* firstarc;
}VNode,AdjList;//表头结点

typedef struct
{
        AdjList vertices;//存储所有顶点
        int vexnum;//顶点总数
        int arcnum;//总边数
}ALGraph;//图的信息

void CreateUDG(ALGraph& G);
int LocateVex(ALGraph& G, VerTexType v);
void printALGraph(ALGraph &G);

int main()
{
        ALGraph G = { {'\0',NULL}, 0,0};
        CreateUDG(G);
        printALGraph(G);

        return 0;
}

void CreateUDG(ALGraph& G)
{
        int i = 0;
        int k = 0;
        VerTexType v1 = 0;
        VerTexType v2 = 0;
        int j = 0;
        ArcNode *p1 = NULL;
        ArcNode *p2 = NULL;

        printf("请输入无向图的总顶点数:");
        scanf_s(" %d", &G.vexnum);

        printf("请输入无向图的总边数:");
        scanf_s(" %d", &G.arcnum);

        for (i = 0; i < G.vexnum; ++i)
        {
                printf("请输入第%d个顶点的值:", i + 1);
                scanf_s(" %c", &(G.vertices.data));
                G.vertices.firstarc = NULL;   //初始化
        }

        for (k = 0; k < G.arcnum; k++)
        {
                printf("请输入第%d条边依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
                scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));

                i = LocateVex(G, v1);
                j = LocateVex(G, v2);

                p1 = (ArcNode*)malloc(sizeof(ArcNode));
                p1->adjvex = j;
                p1->nextarc = G.vertices.firstarc;
                G.vertices.firstarc = p1;//将新结点*p1插入顶点Vi的边表头部

                p2 = (ArcNode*)malloc(sizeof(ArcNode));
                p2->adjvex = i;
                p2->nextarc = G.vertices.firstarc;
                G.vertices.firstarc = p2;//将与*p1对称的新的边结点*p2插入顶点Vj的边表头部
        }
}


//在G的顶点表vexs中获取字符v的下标(数组G.vexs的下标从0开始)
int LocateVex(ALGraph& G, VerTexType v)
{
        int i = 0;
        for (i = 0; i < G.vexnum && (G.vertices.data != v); ++i)
        {
                ;
        }

        return i;
}


//打印邻接表
void printALGraph(ALGraph& G)
{
        int i = 0;
        ArcNode* pMove = NULL;

        for (i = 0; i < G.vexnum; i++)
        {
                printf("\n第%d个顶点为:%c", i + 1, G.vertices.data);

                pMove = G.vertices.firstarc;
                if (pMove)
                {
                        printf("\n与第%d个顶点相邻接的每个顶点在图中的位置(下标值)为:", i + 1);
                        while (pMove)
                        {
                                printf("%d ", pMove->adjvex);
                                pMove = pMove->nextarc;
                        }
                }
                else
                {
                        printf("\n没有与第%d个顶点相邻接的顶点。", i + 1);
                }
        }
}
https://i-blog.csdnimg.cn/direct/11e50d6f3d064f0898897eb04595a79a.png
https://i-blog.csdnimg.cn/direct/8c94c52927ee40a7a39e29719f3eeed2.png
https://i-blog.csdnimg.cn/direct/fea1ccf3c94d4e709b0273eea7713629.png
   一个图的毗邻矩阵表现是唯一的,但其毗邻表表现不唯一。
    不改变图中每个顶点的命名方式,也不改变图的边(每条边的起尽头),
仅改变边的输入序次时,图的毗邻表中每个顶点背面边表中的结点排序方式会发生变化。
由于图中的顶点没变,边也没变,每个顶点及其边表中的内容不会发生变化。
https://i-blog.csdnimg.cn/direct/82f4efd36dd34330bbe81d4d6f8210bd.png
https://i-blog.csdnimg.cn/direct/f9e66b1612e84ddeb7c455fbcf8aa224.png
https://i-blog.csdnimg.cn/direct/be3a103d73bf4d0289deb321cb691fd4.png
接纳毗邻表表现法创建有向图

//采用邻接表表示法创建有向图

#include <stdio.h>
#include <stdlib.h>

#define MVNum 100

typedef int OtherInfo;   //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType;//假设顶点的数据类型为字符型

typedef struct ArcNode
{
        int adjvex;
        struct ArcNode* nextarc;
        OtherInfo info;
}ArcNode;//边结点

typedef struct VNode
{
        VerTexType data;
        ArcNode* firstarc;
}VNode, AdjList;//表头结点

typedef struct
{
        AdjList vertices;//存储所有顶点
        int vexnum;//顶点总数
        int arcnum;//总边数
}ALGraph;//图的信息

void CreateDG(ALGraph& G);
int LocateVex(ALGraph& G, VerTexType v);
void printALGraph(ALGraph& G);

int main()
{
        ALGraph G = { {'\0',NULL}, 0,0 };
        CreateDG(G);
        printALGraph(G);

        return 0;
}

//采用邻接表表示法创建有向图
void CreateDG(ALGraph& G)
{
        int i = 0;
        int k = 0;
        VerTexType v1 = 0;
        VerTexType v2 = 0;
        int j = 0;
        ArcNode* p1 = NULL;
        ArcNode* p2 = NULL;

        printf("请输入有向图的总顶点数:");
        scanf_s(" %d", &G.vexnum);

        printf("请输入有向图的总边数:");
        scanf_s(" %d", &G.arcnum);

        for (i = 0; i < G.vexnum; ++i)
        {
                printf("请输入第%d个顶点的值:", i + 1);
                scanf_s(" %c", &(G.vertices.data));
                G.vertices.firstarc = NULL;   //初始化
        }

        for (k = 0; k < G.arcnum; k++)
        {
                printf("请输入第%d条边依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
                scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));

                i = LocateVex(G, v1);
                j = LocateVex(G, v2);

                p1 = (ArcNode*)malloc(sizeof(ArcNode));
                p1->adjvex = j;
                p1->nextarc = G.vertices.firstarc;
                G.vertices.firstarc = p1;//将新结点*p1插入顶点Vi的边表头部
        }
}


//在G的顶点表vexs中获取字符v的下标(数组G.vexs的下标从0开始)
int LocateVex(ALGraph& G, VerTexType v)
{
        int i = 0;
        for (i = 0; i < G.vexnum && (G.vertices.data != v); ++i)
        {
                ;
        }

        return i;
}


//打印邻接表
void printALGraph(ALGraph& G)
{
        int i = 0;
        ArcNode* pMove = NULL;

        for (i = 0; i < G.vexnum; i++)
        {
                printf("\n第%d个顶点为:%c", i + 1, G.vertices.data);

                pMove = G.vertices.firstarc;
                if (pMove)
                {
                        printf("\n将第%d个顶点作为出度,与其相邻接的每个顶点在图中的位置(下标值)为:", i + 1);
                        while (pMove)
                        {
                                printf("%d ", pMove->adjvex);
                                pMove = pMove->nextarc;
                        }
                }
                else
                {
                        printf("\n将第%d个顶点作为出度,没有与其相邻接的顶点。", i + 1);
                }
        }
}
https://i-blog.csdnimg.cn/direct/25ef799994a643dfb8efac9c4cba5143.png
https://i-blog.csdnimg.cn/direct/1f05e968d7f249f1a8c649e81bb30e19.png
https://i-blog.csdnimg.cn/direct/38157912c9554322a0d6984298dcb490.png
创建有向图的逆毗邻表

//创建有向图的逆邻接表

#include <stdio.h>
#include <stdlib.h>

#define MVNum 100

typedef int OtherInfo;   //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType;//假设顶点的数据类型为字符型

typedef struct ArcNode
{
        int adjvex;
        struct ArcNode* nextarc;
        OtherInfo info;
}ArcNode;//边结点

typedef struct VNode
{
        VerTexType data;
        ArcNode* firstarc;
}VNode, AdjList;//表头结点

typedef struct
{
        AdjList vertices;//存储所有顶点
        int vexnum;//顶点总数
        int arcnum;//总边数
}ALGraph;//图的信息

void CreateDG(ALGraph& G);
int LocateVex(ALGraph& G, VerTexType v);
void printALGraph(ALGraph& G);

int main()
{
        ALGraph G = { {'\0',NULL}, 0,0 };
        CreateDG(G);
        printALGraph(G);

        return 0;
}

//创建有向图的逆邻接表
void CreateDG(ALGraph& G)
{
        int i = 0;
        int k = 0;
        VerTexType v1 = 0;
        VerTexType v2 = 0;
        int j = 0;
        ArcNode* p1 = NULL;
        ArcNode* p2 = NULL;

        printf("请输入有向图的总顶点数:");
        scanf_s(" %d", &G.vexnum);

        printf("请输入有向图的总边数:");
        scanf_s(" %d", &G.arcnum);

        for (i = 0; i < G.vexnum; ++i)
        {
                printf("请输入第%d个顶点的值:", i + 1);
                scanf_s(" %c", &(G.vertices.data));
                G.vertices.firstarc = NULL;   //初始化
        }

        for (k = 0; k < G.arcnum; k++)
        {
                printf("请输入第%d条边依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
                scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));

                i = LocateVex(G, v1);
                j = LocateVex(G, v2);

                p1 = (ArcNode*)malloc(sizeof(ArcNode));
                p1->adjvex = i;
                p1->nextarc = G.vertices.firstarc;
                G.vertices.firstarc = p1;//将新结点*p1插入顶点Vj的边表头部
        }
}


//在G的顶点表vexs中获取字符v的下标(数组G.vexs的下标从0开始)
int LocateVex(ALGraph& G, VerTexType v)
{
        int i = 0;
        for (i = 0; i < G.vexnum && (G.vertices.data != v); ++i)
        {
                ;
        }

        return i;
}


//打印逆邻接表
void printALGraph(ALGraph& G)
{
        int i = 0;
        ArcNode* pMove = NULL;

        for (i = 0; i < G.vexnum; i++)
        {
                printf("\n第%d个顶点为:%c", i + 1, G.vertices.data);

                pMove = G.vertices.firstarc;
                if (pMove)
                {
                        printf("\n将第%d个顶点作为入度,与其相邻接的每个顶点在图中的位置(下标值)为:", i + 1);
                        while (pMove)
                        {
                                printf("%d ", pMove->adjvex);
                                pMove = pMove->nextarc;
                        }
                }
                else
                {
                        printf("\n将第%d个顶点作为入度,没有与其相邻接的顶点。", i + 1);
                }
        }
}
https://i-blog.csdnimg.cn/direct/9ed611e0a11d47efa71e6b48c423c021.png
https://i-blog.csdnimg.cn/direct/f1080b765cd748fc98000043e679d8a7.png
接纳毗邻表表现法创建无向网

#include <stdio.h>
#include <stdlib.h>

#define MVNum 100

typedef int OtherInfo;   //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType;//假设顶点的数据类型为字符型

typedef struct ArcNode
{
        int adjvex;
        struct ArcNode* nextarc;
        OtherInfo info;
}ArcNode;//边结点

typedef struct VNode
{
        VerTexType data;
        ArcNode* firstarc;
}VNode, AdjList;//表头结点

typedef struct
{
        AdjList vertices;//存储所有顶点
        int vexnum;//顶点总数
        int arcnum;//总边数
}ALGraph;//图的信息

void CreateUDN(ALGraph& G);
int LocateVex(ALGraph& G, VerTexType v);
void printALGraph(ALGraph& G);

int main()
{
        ALGraph G = { {'\0',NULL}, 0,0 };
        CreateUDN(G);
        printALGraph(G);

        return 0;
}

//采用邻接表表示法创建无向网
void CreateUDN(ALGraph& G)
{
        int i = 0;
        int k = 0;
        VerTexType v1 = 0;
        VerTexType v2 = 0;
        int j = 0;
        ArcNode* p1 = NULL;
        ArcNode* p2 = NULL;
        int w = 0;

        printf("请输入无向网的总顶点数:");
        scanf_s(" %d", &G.vexnum);

        printf("请输入无向网的总边数:");
        scanf_s(" %d", &G.arcnum);

        for (i = 0; i < G.vexnum; ++i)
        {
                printf("请输入第%d个顶点的值:", i + 1);
                scanf_s(" %c", &(G.vertices.data));
                G.vertices.firstarc = NULL;   //初始化
        }

        for (k = 0; k < G.arcnum; k++)
        {
                printf("请输入第%d条边依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
                scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));               
                printf("请输入第%d条边的权值 : ", k + 1);
                scanf_s(" %d", &w, sizeof(OtherInfo));

                i = LocateVex(G, v1);
                j = LocateVex(G, v2);

                p1 = (ArcNode*)malloc(sizeof(ArcNode));
                p1->adjvex = j;
                p1->info = w;
                p1->nextarc = G.vertices.firstarc;
                G.vertices.firstarc = p1;//将新结点*p1插入顶点Vi的边表头部

                p2 = (ArcNode*)malloc(sizeof(ArcNode));
                p2->adjvex = i;
                p1->info = w;
                p2->nextarc = G.vertices.firstarc;
                G.vertices.firstarc = p2;//将与*p1对称的新的边结点*p2插入顶点Vj的边表头部
        }
}


//在G的顶点表vexs中获取字符v的下标(数组G.vexs的下标从0开始)
int LocateVex(ALGraph& G, VerTexType v)
{
        int i = 0;
        for (i = 0; i < G.vexnum && (G.vertices.data != v); ++i)
        {
                ;
        }

        return i;
}


//打印邻接表
void printALGraph(ALGraph& G)
{
        int i = 0;
        ArcNode* pMove = NULL;

        for (i = 0; i < G.vexnum; i++)
        {
                printf("\n第%d个顶点为:%c", i + 1, G.vertices.data);

                pMove = G.vertices.firstarc;
                if (pMove)
                {
                        printf("\n与第%d个顶点相邻接的每个顶点在网中的位置(下标值)为:", i + 1);
                        while (pMove)
                        {
                                printf("%d ", pMove->adjvex);
                                pMove = pMove->nextarc;
                        }
                }
                else
                {
                        printf("\n没有与第%d个顶点相邻接的顶点。", i + 1);
                }
        }
}
https://i-blog.csdnimg.cn/direct/b951b4c2e5224510b4a24690432fc56b.jpeg
https://i-blog.csdnimg.cn/direct/54d4b126d8f94d50a5aa43db1f00ec04.png
接纳毗邻表表现法创建有向网

#include <stdio.h>
#include <stdlib.h>

#define MVNum 100

typedef int OtherInfo;   //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType;//假设顶点的数据类型为字符型

typedef struct ArcNode
{
        int adjvex;
        struct ArcNode* nextarc;
        OtherInfo info;
}ArcNode;//边结点

typedef struct VNode
{
        VerTexType data;
        ArcNode* firstarc;
}VNode, AdjList;//表头结点

typedef struct
{
        AdjList vertices;//存储所有顶点
        int vexnum;//顶点总数
        int arcnum;//总边数
}ALGraph;//图的信息

void CreateDN(ALGraph& G);
int LocateVex(ALGraph& G, VerTexType v);
void printALGraph(ALGraph& G);

int main()
{
        ALGraph G = { {'\0',NULL}, 0,0 };
        CreateDN(G);
        printALGraph(G);

        return 0;
}

//采用邻接表表示法创建有向网
void CreateDN(ALGraph& G)
{
        int i = 0;
        int k = 0;
        VerTexType v1 = 0;
        VerTexType v2 = 0;
        int j = 0;
        ArcNode* p1 = NULL;
        ArcNode* p2 = NULL;
        int w = 0;

        printf("请输入有向网的总顶点数:");
        scanf_s(" %d", &G.vexnum);

        printf("请输入有向网的总边数:");
        scanf_s(" %d", &G.arcnum);

        for (i = 0; i < G.vexnum; ++i)
        {
                printf("请输入第%d个顶点的值:", i + 1);
                scanf_s(" %c", &(G.vertices.data));
                G.vertices.firstarc = NULL;   //初始化
        }

        for (k = 0; k < G.arcnum; k++)
        {
                printf("请输入第%d条边依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
                scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));               
                printf("请输入第%d条边的权值 : ", k + 1);
                scanf_s(" %d", &w, sizeof(OtherInfo));

                i = LocateVex(G, v1);
                j = LocateVex(G, v2);

                p1 = (ArcNode*)malloc(sizeof(ArcNode));
                p1->adjvex = j;
                p1->info = w;
                p1->nextarc = G.vertices.firstarc;
                G.vertices.firstarc = p1;//将新结点*p1插入顶点Vi的边表头部
        }
}


//在G的顶点表vexs中获取字符v的下标(数组G.vexs的下标从0开始)
int LocateVex(ALGraph& G, VerTexType v)
{
        int i = 0;
        for (i = 0; i < G.vexnum && (G.vertices.data != v); ++i)
        {
                ;
        }

        return i;
}


//打印邻接表
void printALGraph(ALGraph& G)
{
        int i = 0;
        ArcNode* pMove = NULL;

        for (i = 0; i < G.vexnum; i++)
        {
                printf("\n第%d个顶点为:%c", i + 1, G.vertices.data);

                pMove = G.vertices.firstarc;
                if (pMove)
                {
                        printf("\n将第%d个顶点作为出度,与其相邻接的每个顶点在网中的位置(下标值)为:", i + 1);
                        while (pMove)
                        {
                                printf("%d ", pMove->adjvex);
                                pMove = pMove->nextarc;
                        }
                }
                else
                {
                        printf("\n将第%d个顶点作为出度,没有与第%d个顶点相邻接的顶点。", i + 1);
                }
        }
}
https://i-blog.csdnimg.cn/direct/4c7636161e4049c8a542f2f996edc6fb.png
https://i-blog.csdnimg.cn/direct/b38b1be5c20b401a874c32c411af1616.png
创建有向网的逆毗邻表

#include <stdio.h>
#include <stdlib.h>

#define MVNum 100

typedef int OtherInfo;   //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType;//假设顶点的数据类型为字符型

typedef struct ArcNode
{
        int adjvex;
        struct ArcNode* nextarc;
        OtherInfo info;
}ArcNode;//边结点

typedef struct VNode
{
        VerTexType data;
        ArcNode* firstarc;
}VNode, AdjList;//表头结点

typedef struct
{
        AdjList vertices;//存储所有顶点
        int vexnum;//顶点总数
        int arcnum;//总边数
}ALGraph;//图的信息

void CreateDN(ALGraph& G);
int LocateVex(ALGraph& G, VerTexType v);
void printALGraph(ALGraph& G);

int main()
{
        ALGraph G = { {'\0',NULL}, 0,0 };
        CreateDN(G);
        printALGraph(G);

        return 0;
}

//创建有向网的逆邻接表
void CreateDN(ALGraph& G)
{
        int i = 0;
        int k = 0;
        VerTexType v1 = 0;
        VerTexType v2 = 0;
        int j = 0;
        ArcNode* p1 = NULL;
        ArcNode* p2 = NULL;
        int w = 0;

        printf("请输入有向网的总顶点数:");
        scanf_s(" %d", &G.vexnum);

        printf("请输入有向网的总边数:");
        scanf_s(" %d", &G.arcnum);

        for (i = 0; i < G.vexnum; ++i)
        {
                printf("请输入第%d个顶点的值:", i + 1);
                scanf_s(" %c", &(G.vertices.data));
                G.vertices.firstarc = NULL;   //初始化
        }

        for (k = 0; k < G.arcnum; k++)
        {
                printf("请输入第%d条边依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
                scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));
                printf("请输入第%d条边的权值 : ", k + 1);
                scanf_s(" %d", &w, sizeof(OtherInfo));

                i = LocateVex(G, v1);
                j = LocateVex(G, v2);

                p1 = (ArcNode*)malloc(sizeof(ArcNode));
                p1->adjvex = i;
                p1->info = w;
                p1->nextarc = G.vertices.firstarc;
                G.vertices.firstarc = p1;//将新结点*p1插入顶点Vj的边表头部
        }
}


//在G的顶点表vexs中获取字符v的下标(数组G.vexs的下标从0开始)
int LocateVex(ALGraph& G, VerTexType v)
{
        int i = 0;
        for (i = 0; i < G.vexnum && (G.vertices.data != v); ++i)
        {
                ;
        }

        return i;
}


//打印逆邻接表
void printALGraph(ALGraph& G)
{
        int i = 0;
        ArcNode* pMove = NULL;

        for (i = 0; i < G.vexnum; i++)
        {
                printf("\n第%d个顶点为:%c", i + 1, G.vertices.data);

                pMove = G.vertices.firstarc;
                if (pMove)
                {
                        printf("\n将第%d个顶点作为入度,与其相邻接的每个顶点在网中的位置(下标值)为:", i + 1);
                        while (pMove)
                        {
                                printf("%d ", pMove->adjvex);
                                pMove = pMove->nextarc;
                        }
                }
                else
                {
                        printf("\n将第%d个顶点作为入度,没有与第%d个顶点相邻接的顶点。", i + 1);
                }
        }
}
https://i-blog.csdnimg.cn/direct/3571a14a8f5c467ab98d721acd7f2bc1.png
6.4.3 十字链表

接纳十字链表表现法创建有向图

//采用十字链表表示法创建有向图

#include <stdio.h>
#include <stdlib.h>

#define MAX_VERTEX_NUM20

typedef int InfoType;   //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType;//假设顶点的数据类型为字符型

typedef struct ArcBox
{
        int tailvext;
        int headvex;
        struct ArcBox* hlink;
        struct ArcBox* tlink;
        InfoType *info;
}ArcBox;

typedef struct VexNode
{
        VerTexType data;
        ArcBox *firstin;
        ArcBox *firstout;
}VexNode;

typedef struct
{
        VexNode xlist;//表头向量
        int vexnum;//顶点总数
        int arcnum;//总边数
}OLGraph;//图的信息

void CreateOLGraph(OLGraph& G);
int LocateVex(OLGraph& G, VerTexType v);
void printOLGraph(OLGraph& G);

int main()
{
        OLGraph G = { {'\0',NULL,NULL}, 0,0 };
        CreateOLGraph(G);
        printOLGraph(G);

        return 0;
}

//采用十字链表表示法创建有向图
void CreateOLGraph(OLGraph& G)
{
        int i = 0;
        int j = 0;
        int k = 0;
        VerTexType v1 = 0;
        VerTexType v2 = 0;
        ArcBox* p1 = NULL;


        printf("请输入有向图的总顶点数:");
        scanf_s(" %d", &G.vexnum);

        printf("请输入有向图的总边数:");
        scanf_s(" %d", &G.arcnum);

        for (i = 0; i < G.vexnum; ++i)
        {
                printf("请输入第%d个顶点的值:", i + 1);
                scanf_s(" %c", &(G.xlist.data));
                G.xlist.firstin = NULL;
                G.xlist.firstout = NULL;//初始化
        }

        for (k = 0; k < G.arcnum; k++)
        {
                printf("请输入第%d条弧依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
                scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));
                //起点v1是弧尾,终点v2是弧头
                //弧<v1,v2>是v1的出度,是v2的入度

                i = LocateVex(G, v1);
                j = LocateVex(G, v2);
                //起点v1是弧尾,下标值为i;终点v2是弧头,下标值为j
                //弧<v1,v2>是第i+1个顶点的出度firstout,是第j+1个顶点的入度firstin

                p1 = (ArcBox*)malloc(sizeof(ArcBox));

                p1->tailvext = i;//起点v1是弧尾,下标值为i
                p1->headvex = j;   //终点v2是弧头,下标值为j

                //p1弧结点中的链域tlink指向与其弧尾tailvext相同的下一条弧(即指向第i+1个顶点v1的下一个出度firstout)
                p1->tlink = G.xlist.firstout;//p1指向的弧<v1,v2>是第i+1个顶点v1的出度firstout
                G.xlist.firstout = p1;   //前插法将p1插入到第i+1个顶点v1的出度单链表中

                //p1弧结点中的链域hlink指向与其弧头headvex相同的下一条弧(即指向第j+1个顶点v2的下一个入度firstin)
                p1->hlink = G.xlist.firstin;   //p1指向的弧<v1,v2>是第j+1个顶点v2的入度firstin
                G.xlist.firstin = p1;//前插法将p1插入到第j+1个顶点v2的入度单链表中
        }
}


//在G的顶点表xlist中获取字符v的下标(数组G.xlist的下标从0开始)
int LocateVex(OLGraph& G, VerTexType v)
{
        int i = 0;
        for (i = 0; i < G.vexnum && (G.xlist.data != v); ++i)
        {
                ;
        }

        return i;
}


//打印十字链表
void printOLGraph(OLGraph& G)
{
        int i = 0;
        ArcBox* pMoveIn = NULL;
        ArcBox* pMoveOut = NULL;

        for (i = 0; i < G.vexnum; i++)
        {
                printf("\n第%d个顶点为:%c", i + 1, G.xlist.data);

                pMoveOut = G.xlist.firstout;
                if (pMoveOut)
                {
                        printf("\n将第%d个顶点作为出度,与其相邻接的每个顶点在图中的位置(下标值)为:", i + 1);
                        while (pMoveOut)
                        {
                                printf("%d ", pMoveOut->headvex);
                                pMoveOut = pMoveOut->tlink;
                        }
                }
                else
                {
                        printf("\n将第%d个顶点作为出度,没有与其相邻接的顶点。", i + 1);
                }


                pMoveIn = G.xlist.firstin;
                if (pMoveIn)
                {
                        printf("\n将第%d个顶点作为入度,与其相邻接的每个顶点在图中的位置(下标值)为:", i + 1);
                        while (pMoveIn)
                        {
                                printf("%d ", pMoveIn->tailvext);
                                pMoveIn = pMoveIn->hlink;
                        }
                }
                else
                {
                        printf("\n将第%d个顶点作为入度,没有与其相邻接的顶点。", i + 1);
                }

        }
}
https://i-blog.csdnimg.cn/direct/d1b1d2af022242a290e738f7dc81823f.png
https://i-blog.csdnimg.cn/direct/7704c40bda5d41e1b33f00aa6d32b637.png
   该有向图的毗邻矩阵,其中各行、各列中不为0的元素,与其十字链表每个顶点的出度、入度效果有对应关系。
https://i-blog.csdnimg.cn/direct/0a4c60a613874760b0867f8d110cab34.png
接纳十字链表表现法创建有向网

   输入并读取权值,赋值到 弧结点 ArcBox 布局中的 info 成员即可。
//采用十字链表表示法创建有向网

void CreateOLGraph(OLGraph& G)
{
        int i = 0;
        int j = 0;
        int k = 0;
        VerTexType v1 = 0;
        VerTexType v2 = 0;
        ArcBox* p1 = NULL;

        int* w = 0;

        printf("请输入有向网的总顶点数:");
        scanf_s(" %d", &G.vexnum);

        printf("请输入有向网的总边数:");
        scanf_s(" %d", &G.arcnum);

        for (i = 0; i < G.vexnum; ++i)
        {
                printf("请输入第%d个顶点的值:", i + 1);
                scanf_s(" %c", &(G.xlist.data));
                G.xlist.firstin = NULL;
                G.xlist.firstout = NULL;//初始化
        }

        for (k = 0; k < G.arcnum; k++)
        {
                printf("请输入第%d条弧依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
                scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));

                printf("请输入第%d条边的权值 : ", k + 1);
                scanf_s(" %d", w, sizeof(InfoType));//在ArcBox中,info由指向int的指针定义

                i = LocateVex(G, v1);
                j = LocateVex(G, v2);

                p1 = (ArcBox*)malloc(sizeof(ArcBox));

                p1->tailvext = i;
                p1->headvex = j;

                p1->info = w;//赋值到弧结点p1中的info成员

                p1->tlink = G.xlist.firstout;
                G.xlist.firstout = p1;   

                p1->hlink = G.xlist.firstin;   
                G.xlist.firstin = p1;
        }
}
6.4.4 毗邻多重表

接纳毗邻多重表表现法创建无向图

//采用邻接多重表表示法创建无向图

#include <stdio.h>
#include <stdlib.h>

#define MAX_VERTEX_NUM20

typedef enum {unvisited,visited} VisitIf;
typedef int InfoType;   //假设在边结点中的数据域存储边的权值,且边的权值类型为整型
typedef char VerTexType;//假设顶点的数据类型为字符型

typedef struct EBox
{
        VisitIf mark;
        int ivex;
        int jvex;
        struct EBox* ilink;
        struct EBox* jlink;
        InfoType *info;
}EBox;

typedef struct VexBox
{
        VerTexType data;
        EBox* firstedge;
}VexBox;

typedef struct
{
        VexBox adjmulist;//表头向量
        int vexnum;//顶点总数
        int edgenum;//总边数
}AMLGraph;//图的信息

void CreateAMLGraph(AMLGraph& G);
int LocateVex(AMLGraph& G, VerTexType v);
void printAMLGraph(AMLGraph& G);

int main()
{
        AMLGraph G = { {'\0',NULL,NULL}, 0,0 };
        CreateAMLGraph(G);
        printAMLGraph(G);

        return 0;
}

//采用邻接多重表表示法创建无向图
void CreateAMLGraph(AMLGraph& G)
{
        int i = 0;
        int j = 0;
        int k = 0;
        VerTexType v1 = 0;
        VerTexType v2 = 0;
        EBox* p1 = NULL;

        printf("请输入无向图的总顶点数:");
        scanf_s(" %d", &G.vexnum);

        printf("请输入无向图的总边数:");
        scanf_s(" %d", &G.edgenum);

        for (i = 0; i < G.vexnum; ++i)
        {
                printf("请输入第%d个顶点的值:", i + 1);
                scanf_s(" %c", &(G.adjmulist.data));
                G.adjmulist.firstedge = NULL;//初始化
        }

        for (k = 0; k < G.edgenum; k++)
        {
                printf("请输入第%d条弧依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
                scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));
               
                i = LocateVex(G, v1);
                j = LocateVex(G, v2);

                p1 = (EBox*)malloc(sizeof(EBox));

                p1->ivex = i;
                p1->jvex = j;

                p1->ilink = G.adjmulist.firstedge;
                G.adjmulist.firstedge = p1;

                p1->jlink = G.adjmulist.firstedge;
                G.adjmulist.firstedge = p1;
        }
}


//在G的顶点表adjmulist中获取字符v的下标(数组G.xlist的下标从0开始)
int LocateVex(AMLGraph& G, VerTexType v)
{
        int i = 0;
        for (i = 0; i < G.vexnum && (G.adjmulist.data != v); ++i)
        {
                ;
        }

        return i;
}


//打印邻接多重表
void printAMLGraph(AMLGraph& G)
{
        int i = 0;
        EBox* pMove = NULL;

        for (i = 0; i < G.vexnum; i++)
        {
                printf("\n第%d个顶点为:%c", i + 1, G.adjmulist.data);
                pMove = G.adjmulist.firstedge;

                if (pMove)
                {
                        printf("\n与第%d个顶点相邻接的每个顶点在图中的位置(下标值)为:", i + 1);
                        while (pMove)
                        {
                                if (pMove->ivex == i)
                                {
                                        printf("%d ", pMove->jvex);
                                        pMove = pMove->ilink;
                                }
                                else if (pMove->jvex == i)
                                {
                                        printf("%d ", pMove->ivex);
                                        pMove = pMove->jlink;
                                }
                        }
                }
                else
                {
                        printf("\n没有与第%d个顶点相邻接的顶点。", i + 1);
                }       
        }
}
https://i-blog.csdnimg.cn/direct/70076410dc2a4fd6a0ab9ec5f4b24496.png
https://i-blog.csdnimg.cn/direct/7f736d0998f54953b696fbea69bbe318.png
https://i-blog.csdnimg.cn/direct/d7a9dfb6b9384790808f1cdba5534974.png
接纳毗邻多重表表现法创建无向网

   输入并读取权值,赋值到 边结点 EBox 布局中的 info 成员即可。
//采用邻接多重表表示法创建无向网
void CreateAMLGraph(AMLGraph& G)
{
        int i = 0;
        int j = 0;
        int k = 0;
        VerTexType v1 = 0;
        VerTexType v2 = 0;
        EBox* p1 = NULL;

        int* w = 0;

        printf("请输入无向网的总顶点数:");
        scanf_s(" %d", &G.vexnum);

        printf("请输入无向网的总边数:");
        scanf_s(" %d", &G.edgenum);

        for (i = 0; i < G.vexnum; ++i)
        {
                printf("请输入第%d个顶点的值:", i + 1);
                scanf_s(" %c", &(G.adjmulist.data));
                G.adjmulist.firstedge = NULL;//初始化
        }

        for (k = 0; k < G.edgenum; k++)
        {
                printf("请输入第%d条弧依附的两个顶点(用空格间隔,输入结束后按回车): ", k + 1);
                scanf_s(" %c %c", &v1, sizeof(VerTexType), &v2, sizeof(VerTexType));

                printf("请输入第%d条边的权值 : ", k + 1);
                scanf_s(" %d", w, sizeof(InfoType));//在EBox中,info由指向int的指针定义

                i = LocateVex(G, v1);
                j = LocateVex(G, v2);

                p1 = (EBox*)malloc(sizeof(EBox));

                p1->ivex = i;
                p1->jvex = j;

                p1->info = w;   //赋值到边结点p1中的info成员

                p1->ilink = G.adjmulist.firstedge;
                G.adjmulist.firstedge = p1;

                p1->jlink = G.adjmulist.firstedge;
                G.adjmulist.firstedge = p1;
        }
}

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 《数据布局(C语言版)第二版》第六章-图(6.4 图的存储布局——6.4.2 毗邻