c语言数据结构-图的操作

简介: c语言数据结构-图的操作

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)目录

图的概念(http://t.csdn.cn/CH4Bv)

图的顺序存储结构

数组(邻接矩阵)表示法

定义

无向图

有向图

网的邻接矩阵表示法

图的链式存储结构

邻接表表示法

定义:

无向图;

有向图:

小结:


图的概念(http://t.csdn.cn/CH4Bv

图的顺序存储结构

数组(邻接矩阵)表示法

定义

                                 

建立一个顶点表和一个邻接矩阵(表示各个顶点之间关系)。

设图A=(V,E)有n个顶点,则图的邻接矩阵是一个二维数组A.Edge[n][n],

/** 图的类型枚举 */
typedef enum {
    DG,     //有向图   0
    UDG,    //无向图   1
    DN,     //有向网   2
    UDN     //无向网   3
}GraphKind;
/** 图的邻接矩阵存储表示 */
typedef struct {
    char* verTexs[100];                     //顶点数组
    int arcs[100][100];                     //邻接矩阵(权数组)
    int verTexCount;                        //图的顶点数
    int arcCount;                           //图的边/弧数
    GraphKind kind;                         //图的类型
}MatrixGraph;

无向图

特点:

1 、无向图的邻接矩阵是 对称

2 、顶点i的度=第i行(列)中1的个数

完全图的领接矩阵中,对角元素为0,其余1

/** 使用邻接矩阵表示法创建无向图 */
int CreateUDG(MatrixGraph* G) 
{
    G->kind = UDG;      //设置当前创建图的类型为无向图
    printf("请输入无向图的顶点数:");
    scanf("%d", &G->verTexCount);
    printf("请输入边的数量:");
    scanf("%d", &G->arcCount);
    printf("依次输入顶点信息\n");
    for (int i = 0; i < G->verTexCount; i++)
    {
        G->verTexs[i] = (char *)malloc(sizeof(char) * 10);
        printf("顶点%d:", i + 1);
        scanf("%s", G->verTexs[i]);
    }
    //初始化邻接矩阵,所有边的权值设置为0
    for (int i = 0; i < G->verTexCount; i++)
    {
        for (int j = 0; j < G->verTexCount; j++)
        {
            G->arcs[i][j] = 0;
        }
    }
    printf("请输入顶点和邻接顶点信息,构建邻接矩阵\n");
    for (int i = 0; i < G->arcCount; i++)
    {
        char * vex1 = (char *)malloc(sizeof(char) * 10);
        char * vex2 = (char *)malloc(sizeof(char) * 10);
        printf("顶点:");
        scanf("%s", vex1);
        printf("邻接点:");
        scanf("%s", vex2);
        //分别获得两个顶点在顶点数组中的坐标
        int x = LocateVex(G, vex1);
        int y = LocateVex(G, vex2);
        if (x == -1 || y == -1) 
        {
            return 0;
        }
        G->arcs[x][y] = 1;
        G->arcs[y][x] = G->arcs[x][y];      //无向图的邻接矩阵是对称的
        free(vex1);
        free(vex2);
    }
    return 1;
}

有向图

特点:

1 、 有向图的邻接矩阵 可能是不对称

2 、 顶点的 出度=第i行元素之和

       顶点的 入度=第i 列元素之和

       顶点的= 第i 行元素之和+ 第i列元素之和

/** 使用邻接矩阵表示法创建有向图 */
int CreateDG(MatrixGraph* G) {
    G->kind = DG;      //设置当前创建图的类型为有向图
    printf("请输入有向图的顶点数:");
    scanf("%d", &G->verTexCount);
    printf("请输入边的数量:");
    scanf("%d", &G->arcCount);
    printf("依次输入顶点信息\n");
    for (int i = 0; i < G->verTexCount; i++) {
        G->verTexs[i] = (char *)malloc(sizeof(char) * 10);
        printf("顶点%d:", i + 1);
        scanf("%s", G->verTexs[i]);
    }
    //初始化邻接矩阵,所有边的权值设置为0
    for (int i = 0; i < G->verTexCount; i++) {
        for (int j = 0; j < G->verTexCount; j++) {
            G->arcs[i][j] = 0;
        }
    }
    printf("请输入顶点和邻接顶点信息,构建邻接矩阵\n");
    for (int i = 0; i < G->arcCount; i++) {
        char * vex1 = (char *)malloc(sizeof(char) * 10);
        char * vex2 = (char *)malloc(sizeof(char) * 10);
        printf("顶点:");
        scanf("%s", vex1);
        printf("邻接点:");
        scanf("%s", vex2);
        //分别获得两个顶点在顶点数组中的坐标
        int x = LocateVex(G, vex1);
        int y = LocateVex(G, vex2);
        if (x == -1 || y == -1) {
            return 0;
        }
        G->arcs[x][y] = 1;
        //G->arcs[y][x] = G->arcs[x][y];      //有向图的邻接矩阵有可能不对称
        free(vex1);
        free(vex2);
    }
    return 1;
}

网的邻接矩阵表示法

图的链式存储结构

邻接表表示法

定义:

指数组与链表相结合的储存方法

对每个顶点V𝑗 建立一个单链表,把与V 𝑗 有关联的边的信息链接起来,每个结点设为3个域

1 、每个单链表有一个 头结点 (设为 2个域)),存V𝒋 信息

2 、每个单链表的头结点另外用顺序存储结构存储

/** 图的类型枚举 */
typedef enum
{
    DG,     //有向图   0
    UDG,    //无向图   1
    DN,     //有向网   2
    UDN     //无向网   3
}GraphKind;
/** 边/弧的结点 */
typedef struct node {
    int adjVex;                     //该边指向这条边邻接点的下标
    struct node* nextEdge;         //指向下一条边结点的指针
    struct node* nextArc;          //指向下一个弧结点的指针
    int weight;                 //权重
}EdgeNode, ArcNode;
/** 顶点结点 */
typedef struct vexNode {
    char* vex;                 //顶点值
    EdgeNode* firstEdge;           //指向第一条边的指针
    ArcNode* firstArc;             //指向第一条弧的指针
}VNode, AdjList[100];
/** 邻接表实现的图结构 */
typedef struct adjGraph {
    AdjList vexes;                  //顶点数组
    int vexCount;                   //顶点数量
    int edgeCount;                  //图的边数
    int arcCount;                   //图的弧数
    GraphKind kind;                 //图的类型
}AdjListGraph;

无向图;

 

注意:邻接表不唯一,因为各个边结点的链入顺序是任意的

TD(V𝒋 ) = 单链表中链接的结点个数

/** 返回顶点vex在顶点数组中的下标,没有找到返回-1 */
int LocateVex_AdjList(AdjListGraph* G, char* vex) {
    int index = -1;
    for (int i = 0; i < G->vexCount; i++) {
        if (strcmp(vex, G->vexes[i].vex) == 0) {
            index = i;
            break;
        }
    }
    return index;
}
/** 采用邻接表表示法创建无向图 */
int CreateUDG_AdjList(AdjListGraph* G) {
    G->kind = UDG;
    printf("请输入顶点数量:");
    scanf("%d", &G->vexCount);
    printf("请输入边的数量:");
    scanf("%d", &G->edgeCount);
    printf("请依次输入顶点信息\n");
    for (int i = 0; i < G->vexCount; i++) {
        G->vexes[i].vex = (char*)malloc(sizeof(char) * 10);
        printf("顶点%d:", i + 1);
        scanf("%s", G->vexes[i].vex);
        //初始化邻接表,把边置空
        G->vexes[i].firstEdge = NULL;
    }
    printf("请输入顶点和邻接点信息,构建邻接表\n");
    for (int i = 0; i < G->edgeCount; i++) {
        char* vex1 = (char*)malloc(sizeof(char) * 10);
        char* vex2 = (char*)malloc(sizeof(char) * 10);
        printf("顶点:");
        scanf("%s", vex1);
        printf("邻接点:");
        scanf("%s", vex2);
        int x = LocateVex_AdjList(G, vex1);
        int y = LocateVex_AdjList(G, vex2);
        if (x == -1 || y == -1) {
            free(vex1);
            free(vex2);
            return 0;
        }
        EdgeNode* edgeNode = (EdgeNode*)malloc(sizeof(EdgeNode));
        edgeNode->adjVex = x;
        edgeNode->nextEdge = G->vexes[y].firstEdge;
        edgeNode->weight = 0;
        G->vexes[y].firstEdge = edgeNode;
        edgeNode = (EdgeNode*)malloc(sizeof(EdgeNode));
        edgeNode->adjVex = y;
        edgeNode->nextEdge = G->vexes[x].firstEdge;
        edgeNode->weight = 0;
        G->vexes[x].firstEdge = edgeNode;
        free(vex1);
        free(vex2);
    }
    return 1;
}

有向图:

TD(V𝒋 ) = OD(V𝒋 ) + ID(V𝒋 )

小结:

相关文章
|
21天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
103 9
|
1月前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
66 4
|
20天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
60 16
|
20天前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
71 8
|
22天前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
50 4
|
24天前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
56 3
|
24天前
|
存储 算法 C语言
C语言数据结构(2)
【10月更文挑战第21天】
|
1月前
|
存储 算法 C语言
【趣学C语言和数据结构100例】
《趣学C语言和数据结构100例》精选5个编程问题,涵盖求最大公约数与最小公倍数、字符统计、特殊序列求和及阶乘计算等,通过实例讲解C语言基础与算法思维,适合初学者实践学习。
74 1
|
1月前
|
存储 C语言
探索C语言数据结构:利用顺序表完成通讯录的实现
本文介绍了如何使用C语言中的顺序表数据结构实现一个简单的通讯录,包括初始化、添加、删除、查找和保存联系人信息的操作,以及自定义结构体用于存储联系人详细信息。
21 2
|
22天前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
40 0