数据结构与算法--图的存储方式

1. 图的定义

  • 定义:图是由顶点的有穷非空结合和顶点之间的集合组成,数据元素(顶点)之间具有任意关系,图中任意两个数据元素之间都可能相关

  • 各种图:

无向图(顶点到顶点之间的边没有方向,则称这条边为无向边)

有向图(若从顶点 到顶点 的边有方向,则称这条边为有向边,也称为弧)

顶点A顶点D的边就是弧,用<A, D>表示弧,注意不能写成<D, A>
上图可以表示为G= (V2,{E2}),其中顶点集合V2={A,E,C,D}, 弧集合E2={<A,D>,<A,E>,<A,C>,<E,D>}

无向完全图

有向完全图

有些图的边具有与它相关的数字,这种与图的边或弧相关的数叫做。这些权可以表示从一个顶点到另一个顶点的距离或耗费。

这种带权的图通常称为。如下图就是一张带权的图,即标识中国四大城市的直线距离的网,此图中的权就是两地的距离。

广度优先搜索算法:数据结构是队列。通过将顶点存入队列中,最先入队列的顶点先被探索。

深度优先搜索算法:数据结构是栈。通过将顶点存入栈中,沿着路径探索顶点,存在新的相邻顶点就去访问

2. 图的存储

2.1. 图的存储介绍

图用 邻接矩阵存储方式 来存储

  1. 一个一维数组存储图中顶点信息

  2. 一个二维数组(称为邻接矩阵)存储图中的边或弧的信息。

图Gn个顶点,则邻接矩阵是一个nxn的方阵,定义为:

如下无向图:

如下有向图

我们知道,每条边上带有权值叫做,那么在存储的时候,可以采用权值代替矩阵中的0、1,权值不存在的元素之间用表示,如下图,左图是一个有向网图,右图就是它的邻接矩阵。

2.2. 邻接矩阵

定义一个数组,存储顶点,定义一个邻接矩阵(二维数组)

#define OK    1
#define ERROR 0
#define TRUE  1
#define FALSE 0
#define MAXVEX 100 // 最大顶点数
#define INFINITYC 0

typedef int  Status;
typedef char VertexType;  // 顶点类型
typedef int  EdgeType;    // 边的权值的类型

// 定义图的结构
typedef struct {
    VertexType vers[MAXVEX];       // 顶点表
    EdgeType   arc[MAXVEX][MAXVEX];// 邻接矩阵
    int        numNodes;           // 顶点数
    int        numEdges;           // 边数
}MGraph;

图的存储方法:

void CreateMGraph(MGraph *G){
    int i, j, k, m;
    // 1.输入顶点数
    printf("输入顶点数:");
    scanf("%d", &G->numNodes);
    // 2.输入边数
    printf("输入边数:");
    scanf("%d", &G->numEdges);
    
    printf("顶点数:%d,边数:%d\n",G->numNodes,G->numEdges);
    
    // 3.输入顶点表
    printf("输入顶点:");
    for (i = 0; i <= G->numNodes; i++) {
        scanf("%c", &G->vers[i]);
    }
    // 4.初始化邻接矩阵
    for (i = 0; i < G->numNodes; i++) {
        for (j = 0; j < G->numNodes; j++) {
            G->arc[i][j] = INFINITY;
        }
    }
    // 5.输入边信息
    for (k = 0; k < G->numEdges; k++) {
        printf("输入边(vi,vj)上的下标i,下标j,权w(逗号分隔)\n");
        scanf("%d,%d,%d", &i, &j, &m);
        
        G->arc[i][j] = m;
        //如果无向图,矩阵对称;
        //G->arc[j][i] = G->arc[i][j];
        
    }
    
    // 6.打印
    for (int i = 0; i < G->numNodes; i++) {
        printf("\n");
        for (int j = 0; j < G->numNodes; j++) {
            printf("%d ",G->arc[i][j]);
        }
    }
    printf("\n");
}

2.3. 邻接表

#define M 100    //顶点最大个数
#define TRUE 1
#define FALSE 0

typedef char Element;

// 定义邻接表节点
typedef struct Node {
    int      adj_vex_index;    // 弧头下标
    Element  data;             // 权重
    struct Node *next;         // 边指针
}EdgeNode;

// 定义顶点表结构
typedef struct vNode {
    Element     data;        // 权重
    EdgeNode    * firstedge; // 顶点的下一个
}VertexNode,Adjlist[M];

// 定义图结构
typedef struct Graph{
    Adjlist adjlist;      // 顶点表
    int     arc_num;      // 边数
    int     node_num;     // 顶点数
    int    is_directed;  // 是否是有向图
}Graph, *GraphLink;

图的存储(邻接表)

void creatGraph(GraphLink *g){
    
    int i, j, k;
    EdgeNode *p;
    
    // 输入边数,顶点数,是否有向
    printf("输入顶点数目,边数和有向?:\n");
    scanf("%d %d %d", &(*g)->node_num, &(*g)->arc_num, &(*g)->is_directed);
    
    // 输入顶点信息
    for (i = 0; i < (*g)->node_num; i++) {
        getchar();
        scanf("%c", &(*g)->adjlist[i].data);
        (*g)->adjlist[i].firstedge = NULL;
    }
    printf("输入边信息:\n");
    for (k = 0; k < (*g)->arc_num; k++) {
        getchar();
        scanf("%d %d", &i, &j);
        
        // 创建新节点
        p = (EdgeNode *)malloc(sizeof(EdgeNode));
        // 弧头的下标
        p->adj_vex_index = j;
        // 头插法
        p->next = (*g)->adjlist[i].firstedge;
        // 将顶点数组[i].firstedge 设置为p
        (*g)->adjlist[i].firstedge = p;
        
        // 判断是否是有向
        if (!(*g)->is_directed) {
            // 创建新节点
            p = (EdgeNode *)malloc(sizeof(EdgeNode));
            // 弧头的下标
            p->adj_vex_index = i;
            // 头插法
            p->next = (*g)->adjlist[j].firstedge;
            // 将顶点数组[i].firstedge 设置为p
            (*g)->adjlist[j].firstedge = p;
        }
    }
}

void putGraph(GraphLink g){
    int i;
    printf("邻接表中存储信息:\n");
    //遍历一遍顶点座标,每个再进去走一次
    for (i = 0; i < g->node_num; i++) {
        EdgeNode * p = g->adjlist[i].firstedge;
        while (p) {
            printf("%c->%c ", g->adjlist[i].data, g->adjlist[p->adj_vex_index].data);
            p = p->next;
        }
        printf("\n");
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章