12.图——数组表示法

这篇博客探讨了图的数组表示法,包括无向图的邻接矩阵及其存储特性。作者提到了在数组表示法中,无向图的邻接矩阵是上下对称的,但未进行压缩存储,导致空间浪费。接着,文章详细阐述了深度优先遍历(DFS)和广度优先遍历(BFS)的概念,指出DFS利用递归,而BFS借助队列实现,并且两种遍历都需要使用标志数组避免重复遍历。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

无向图:V是顶点的集合,VR是弧的集合,弧用(顶点,顶点)表示。有n个顶点,n(n-1)/2条弧的图,是无向完全图。
权:图的弧的相关系数。
网:带权的图。
子图:顶点和弧都包含于原图的图
邻接:两顶点之间有弧,则无向图a、b互为邻接点,有向图a邻接到b。
依附:弧依附于其两个顶点。
顶点的度:与顶点相关联的弧的个数。有向图有入度、出度之分。
路径:从a到b途径顶点组成的序列。有向图路径有向,无向图路径无向。
路径长度:路径上弧的个数。
回路/环:第一个顶点和最后一个顶点相同的路径。
简单路径:顶点不重复的路径。
简单回路/环:除第一个和最后一个顶点外,其余顶点不重复的回路。
连通:某两个顶点间有路径,则这两个顶点连通。
连通图:无向图中任意两个顶点都连通的图。
连通分量:无向图中能够连通极大节点个数的子图。
强连通图:有向图中任意两个顶点间相互有路径的图。
强连通分量:有向图中能够连通极大节点个数的子图(不一定顶点相互有路径,有一方有就行)。
连通图的生成树:包含连通图所有的n个顶点,却只有n-1个边。加上一个边就形成环。
有向树:仅有一个顶点入度为0,其余顶点入度均为1的有向图。
有向图的生成森林:由若干个不相交的有向树组成,这些有向树包含了有向图的所有顶点,却不包含所有边。


图的存储结构:数组表示法、邻接法、十字链表、邻接多重表。
本文针对数组表示法。
数组存储法用两个数组存储顶点和边信息。
顶点就是char型数组,边是一个包含权和其他信息的结构体构成的矩阵数组。

指向图的指针不仅要包含顶点和边,还要包含当前顶点数和边数。为了将4种图结合起来写成一个函数,又加上了图种类的元素。


程序:

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

#define MAX_VERTEX_NUM 20  //最大顶点个数
typedef enum {DG,DN,UDG,AN} GraphKind;   //{有向图,有向网,无向图,无向网}
#define MAX_NAME 5  //顶点字符串的最大长度+1
#define MAX_INFO 20  //相关信息字符串的最大长度+1
typedef int status;
typedef char VertexType[MAX_NAME];
int has_info = 0;

typedef struct
{
    int adj;  //边有无
    char *info;  //该边相关信息的指针
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct
{
    VertexType vertex[MAX_VERTEX_NUM];  //顶点数组,每一个元素是char型数组
    AdjMatrix arcs;  //邻接矩阵,每一个元素代表一条边
    int vexnum,arcnum;  //图的当前顶点数和弧数
    GraphKind kind;  //图的种类标志
}Graph;  //图



//查找G中u顶点位置并返回
int locate_vertex(Graph *G,VertexType u)
{
    int i;
    for(i = 0;i < G->vexnum;++i)
        if(strcmp(u,G->vertex[i]) == 0)
            return i;
    return -1;
}

//创建有向图
status CreateDG(Graph *G)
{
    int i,j,k,l;
    char s[MAX_INFO],*info;
    VertexType va,vb;
    
    printf("please input the directed graph's vertex number, edge number, and if the edge has information(yes:1, no:0): ");
    scanf("%d %d %d",&G->vexnum,&G->arcnum,&has_info);  //输入顶点个数,边个数及是否有其他信息
    printf("please input %d string of vertex value(<%d chars of each string):\n",G->vexnum,MAX_NAME);
    
    for(i = 0;i < G->vexnum;i++)  //设置顶点
        scanf("%s",G->vertex[i]);
    for(i = 0;i < G->vexnum;++i)  //邻接矩阵置空
        for(j = 0;j < G->vexnum;++j){
            G->arcs[i][j].adj = 0;
            G->arcs[i][j].info = NULL;
        }
    printf("please input tail head of %d edges in order: \n",G->arcnum);  //设置邻接矩阵
    for(k = 0;k < G->arcnum;++k){
        printf("%d 's edge:\n",k + 1);
        scanf("%s %s",va,vb);
        i = locate_vertex(G,va);
        j = locate_vertex(G,vb);
        G->arcs[i][j].adj = 1;  //设置邻接矩阵
        if(has_info){
            printf("please input the information of this edge(<%d chars of this edge): ",MAX_INFO);
            scanf("%s",s);
            l = strlen(s);
            if(l){
                info = (char*)malloc((l + 1) * sizeof(char));
                strcpy(info,s);
                G->arcs[i][j].info = info;
            }
        }
    }    
    G->kind = DG;
    return 1;
}

//创建有向网
status CreateDN(Graph *G)
{
    int i,j,k,l,w;
    char s[MAX_INFO],*info;
    VertexType va,vb;
    
    printf("please input the directed graph's vertex number, edge number, and if the edge has information(yes:1, no:0): ");
    scanf("%d %d %d",&G->vexnum,&G->arcnum,&has_info);  //输入顶点个数,边个数及是否有其他信息
    printf("please input %d string of vertex value(<%d chars of each string):\n",G->vexnum,MAX_NAME);
    for(i = 0;i < G->vexnum;++i)  //依次输入顶点的值
        scanf("%s",G->vertex[i]);
    for(i = 0;i < G->vexnum;++i)  //邻接矩阵置空
        for(j = 0;j < G->vexnum;++j){
            G->arcs[i][j].adj = INT_MAX;
            G->arcs[i][j].info = NULL;
        }
    printf("please input tail head power of %d edges in order: \n",G->arcnum);
    for(k = 0;k < G->arcnum;++k){
    	printf("%d 's edge:\n",k + 1);
        scanf("%s %s %d",va,vb,&w);
        i = locate_vertex(G,va);
        j = locate_vertex(G,vb);
        G->arcs[i][j].adj = w;  //设置邻接矩阵
        if(has_info){
            printf("please input the information of this edge(<%d chars of this edge): ",MAX_INFO);
            scanf("%s",s);
            l = strlen(s);
            if(l){
                info = (char*)malloc((l + 1) * sizeof(char));
                strcpy(info,s);
                G->arcs[i][j].info = info;
            }
        }
    }    
    
    G->kind = DN;
    return 1;
}

//创建无向图
status CreateUDG(Graph *G)
{
    int i,j,k,l;
    char s[MAX_INFO],*info;
    VertexType va,vb;
    
    printf("please input the undirected graph's vertex number, edge number, and if the edge has information(yes:1, no:0): ");
    scanf("%d %d %d",&G->vexnum,&G->arcnum,&has_info);  //输入顶点个数,边个数及是否有其他信息
    printf("please input %d string of vertex value(<%d chars of each string):\n",G->vexnum,MAX_NAME);
    for(i = 0;i < G->vexnum;++i)  //依次输入顶点的值
        scanf("%s",G->vertex[i]);
    for(i = 0;i < G->vexnum;++i)  //邻接矩阵置空
        for(j = 0;j < G->vexnum;++j){
            G->arcs[i][j].adj = 0;
            G->arcs[i][j].info = NULL;
        }
    printf("please input vertex1 vertex2 of the %d edges in order: \n",G->arcnum);
    for(k = 0;k < G->arcnum;++k){
    	printf("%d 's edge:\n",k + 1);
        scanf("%s %s",va,vb);
        i = locate_vertex(G,va);
        j
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值