图的存储结构(精编)

一.邻接矩阵存储方法

  邻接矩阵是表示顶点之间相邻关系的矩阵。设G=(V,E)是具有n个顶点的图,顶点的顺序依次是(v0,v1,v2,.....vn-1),则G的邻接矩阵A是n阶方阵:

  若A是无向图,A[i][j]=1,表示i,j之间有一条边,i到j可达且j到i可达。若A是无向图,A[i][j]=1,表示i到j可达,j到i不可达。

  邻接矩阵的特点如下:

  (1)图的邻接矩阵表示是唯一的;

  (2)无向图的邻接矩阵是对称矩阵。压缩方法:存储时只需存储上三角或下三角;

  (3)当邻接矩阵是稀疏矩阵时,当图中顶点较多时,可以采用三元组表的方法存储;

  (4)对于无向图,邻接矩阵的第i行(或第i列)非零元素的个数正好是第i个顶点的度。

    对于有向图,第i行(第i列)非零元素的个数正好是第i个顶点的出度(入度);

  局限性:要确定图中有多少条边,必须按行,按列对每个元素进行检测,花费时间代价很大;

 1 #define M 最大顶点个数
 2 typedef struct
 3 {
 4     int no;//顶点编号
 5     ...//其他信息
 6 }vertextype;
 7 typedef struct//定义图
 8 {
 9     int edge[M][M];//邻接矩阵
10     int n,e;//顶点数,弧数
11     vertextype vexs[M];//存放顶点信息
12 }Mgraph;

  例如:要存储10个点直接的关系,可以用一个10*10的邻接矩阵来存储,代码如下:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #define M 11
 4 typedef struct
 5 {
 6     int no;
 7 }vertextype;
 8 typedef struct
 9 {
10     int edge[M][M];
11     int n,e;
12     vertextype vexs;
13 }Mgraph;
14 int main()
15 {
16     Mgraph A;
17     int a,b;
18     memset(A.edge,0,sizeof(A.edge));
19     A.n=10;
20     scanf("%d",&A.e);
21     for(int i=1;i<=A.e;i++)
22     {
23         scanf("%d%d",&a,&b);
24         A.edge[a][b]=1;
25     }
26     for(int i=1;i<=10;i++)
27     {
28         for(int j=1;j<=10;j++)
29         {
30             printf("%d ",A.edge[i][j]);
31         }
32         printf("\n");
33     }
34     return 0;
35 }

二.邻接表存储方法

  在我们平时使用邻接矩阵的时候经常会遇到以下三种情况: 
    1. 对于一个|V|很大的图,无法使用邻接矩阵进行存储。对于256M的内存,所以我们最多能使用的|V| = 8192的邻接矩阵。 
    2. 对于某些稀疏图或者无根树,每个节点都拥有大小为|V|的数组,但实际使用到的只有很小一部分,造成了很多空间上的浪费。 
    3. 有时两个点之间不止存在有一条边,这是用邻接矩阵就无法同时表示两条以上的边。 
  由以上情况我们想到了一种特殊的图存储方式,让每个节点拥有的数组大小刚好就等于它所连接的边数。

  邻接表存储方法是一种链式分配和链式分配相结合的存储方法。在邻接表中,对图中的每个顶点建立一个单链表,第i个单链表中的结点依附于顶点vi的边(对有向图是以顶点vi为尾的弧)。每个单链表上附设一个表头结点。

  表结点由三个域组成,adjvex存储与vi邻接的点在图中的位置,nextarc存储下一条边或弧的结点,data存储与边或弧相关的信息如权值。;表头结点由两个域组成,分别指向链表中第一个顶点和存储vi的名或其他信息。

  邻接表的特点如下:

  (1)表示不唯一;

  (2)对于稀疏图,邻接表比邻接矩阵更省空间;

  (3)对于无向图,vi对应第i个链表的表结点个数等于顶点得度;

    对于有向图,vi对应第i个链表的表结点个数等于顶点的出度,其入度为邻接表中所有adjvex值域为i的边结点数目。

 1 typedef struct ANode//弧的结点结构类型
 2 {
 3     int adjvex;//弧的终点位置
 4     sgruct ANode *nextarc;//指向下一条弧的指针
 5 }ArcNode;
 6 typedef struct VNode//邻接表头结点类型
 7 {
 8     Vertex data;//顶点信息
 9     ArcNode *firstarc;//指向第一条弧
10 }Vnode;
11 typedef Vnode A[M];//A是邻接表类型
12 typedef struct
13 {
14     A adjlist;//邻接表
15     int n,e;
16 }Agraph;//图的类型

逆邻接表:就是在有向图的邻接表中,对每个顶点,连接的是指向该顶点的弧。

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #define  MaxVertexNum 100
 4 typedef char VertexType;
 5 typedef struct node   //边表节点
 6 {
 7     int adjvex;
 8     node* next;
 9 } EdgeNode;
10 typedef struct     //顶点表节点
11 {
12     VertexType vertex;
13     EdgeNode* firstedge;
14 } VertexNode;
15 typedef VertexNode AdjList[MaxVertexNum];
16 typedef struct
17 {
18     AdjList adjlist;
19     int n,e;
20
21 } ALGraph;
22 void create(ALGraph*);
23 void main()
24 {
25     ALGraph* G= (ALGraph*)malloc(sizeof(ALGraph));
26     create(G);
27     for (int i=0; i< G->n; i++)
28     {
29         printf("%d->",i);
30         while(G->adjlist[i].firstedge!=NULL)
31         {
32             printf("%d->",G->adjlist[i].firstedge->adjvex);
33             G->adjlist[i].firstedge=G->adjlist[i].firstedge->next;
34
35         }
36         printf("\n");
37     }
38 }
39 void create(ALGraph* G)
40 {
41     int i,j,k,w,v;
42     EdgeNode *s;
43     printf("读入顶点数和边数");
44     scanf("%d,%d",&G->n,&G->e);
45     for (i=0; i<G->n; i++)
46     {
47         fflush(stdin);
48         printf("建立顶点表");
49         G->adjlist[i].vertex=getchar();
50         G->adjlist[i].firstedge=NULL;
51     }
52     printf("建立边表\n");
53     for (k=0; k<G->e; k++)
54     {
55         printf("读入(vi-vj)的顶点对序号");
56         scanf("%d,%d",&i,&j);
57         s=(EdgeNode*)malloc(sizeof(EdgeNode));
58         s->adjvex=j;
59         s->next=G->adjlist[i].firstedge;  //插入表头
60         G->adjlist[i].firstedge=s;
61         s=(EdgeNode*)malloc(sizeof(EdgeNode));
62         s->adjvex=i;
63         s->next=G->adjlist[j].firstedge;
64         G->adjlist[j].firstedge=s;
65
66     }
67 }

三. 十字链接表存储方法

  实际上是邻接表和逆邻接表的结合。在十字邻接表中,每个边结点对应图中的一条边,把每一条边的边结点分别组织到以起始顶点为头结点的的链表和以终点结点为头结点的链表中。

四. 邻接多重表存储方法

  邻接多重表(Adjacency Multilist)是无向图的另一中链式存储结构。虽然邻接表是无向图的一种有效的存储结构,在邻接表中容易求顶点和边的各种信息。但是,在邻接表中的每一条边的两个结点分别在不同的链表中。这给某些图的操作带来不便。(如对搜索过的边标记或删除一条边等)邻接多重表的结构和十字链表相似。给每一条边用一个结点表示!

在邻接多重表中,所有依附于同一顶点的边串联在同一链表中,由于每条边依附于两个顶点,则每个边结点同时链接在两个链表中。
可见,对无向图而言,其邻接多重表和邻接表的差别,仅仅在于同一条边在邻接表中用两个结点表示,而在邻接多重表中只有一个结点。
因此,除了在边结点增加一个标志域外,邻接多重表所需的存储量和邻接表相同。因此,各种基本操作的实现亦和邻接表相似。

第三第四种不常用,此处暂不做深入探讨。

各位晚安~~

时间: 2024-09-29 18:57:18

图的存储结构(精编)的相关文章

java 数据结构 图中使用的一些常用算法 图的存储结构 邻接矩阵:图的邻接矩阵存储方式是用两个数组来标示图。一个一位数组存储图顶点的信息,一个二维数组(称为邻接矩阵)存储图中边或者弧的信息。 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 实例如下,左图是一个无向图。右图是邻接矩阵表示:

以下内容主要来自大话数据结构之中,部分内容参考互联网中其他前辈的博客. 图的定义 图是由顶点的有穷非空集合和顶点之间边的集合组成,通过表示为G(V,E),其中,G标示一个图,V是图G中顶点的集合,E是图G中边的集合. 无边图:若顶点Vi到Vj之间的边没有方向,则称这条边为无项边(Edge),用序偶对(Vi,Vj)标示. 对于下图无向图G1来说,G1=(V1, {E1}),其中顶点集合V1={A,B,C,D}:边集合E1={(A,B),(B,C),(C,D),(D,A),(A,C)}: 有向图:若

数据结构之图(一)图的存储结构

图的存储结构相对于线性表和树来说更为复杂,因为图中的顶点具有相对概念,没有固定的位置.那我们怎么存储图的数据结构呢?我们知道,图是由(V, E)来表示的,对于无向图来说,其中 V = (v0, v1, ... , vn),E = { (vi,vj) (0 <=  i, j <=  n且i 不等于j)},对于有向图,E = { < vi,vj > (0 <=  i, j <=  n且i 不等于j)}.V是顶点的集合,E是边的集合.所以我们只要把顶点和边的集合储存起来,那么

数据结构 - 图的存储结构

图的抽象数据类型定义 图是一种数据结构,加上一组基本操作就构成了图的抽象数据类型. 图的抽象数据类型定义如下: ADT Graph{ 数据对象V:具有相同特性的数据元素的集合,称为顶点集. 数据关系R:R={VR} VR={<v,w>|<v,w>| v,w?V∧p(v,w) ,<v,w>表示 从v到w的弧,P(v,w)定义了弧<v,w>的信息 } 基本操作P: Create_Graph() : 图的创建操作. 初始条件:无. 操作结果:生成一个没有顶点的空图

《大话数据结构》笔记(7-2)--图:存储结构

第七章  图 图的存储结构 图不能用简单的顺序存储结构来表示. 而多重链表的方式,即以一个数据域和多个指针域组成的结点表示图中的一个顶点,尽管可以实现图结构,但是会有问题,比如若各个顶点的度数相差很大,按度数最大的顶点设计结点结构会造成很多存储单元的浪费,而若按每个顶点自己的度数设计不同的顶点结构,又带来操作的不便. 对于图来说,如何对它实现物理存储是个难题.图有以下五种不同的存储结构. 邻接矩阵 图的邻接矩阵(Adjacency Matrix)存储方式使用过两个数组来表示图.一个一维数组存储图

图的存储结构(邻接矩阵)

图的存储结构(邻接矩阵) 让编程改变世界 Change the world by program 图的存储结构 图的存储结构相比较线性表与树来说就复杂很多. 我们回顾下,对于线性表来说,是一对一的关系,所以用数组或者链表均可简单存放.树结构是一对多的关系,所以我们要将数组和链表的特性结合在一起才能更好的存放. 那么我们的图,是多对多的情况,另外图上的任何一个顶点都可以被看作是第一个顶点,任一顶点的邻接点之间也不存在次序关系. 我们仔细观察以下几张图,然后深刻领悟一下: 因为任意两个顶点之间都可能

(转)数据结构之图(存储结构、遍历)

一.图的存储结构 1.1 邻接矩阵 图的邻接矩阵存储方式是用两个数组来表示图.一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中的边或弧的信息. 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 看一个实例,下图左就是一个无向图. 从上面可以看出,无向图的边数组是一个对称矩阵.所谓对称矩阵就是n阶矩阵的元满足aij = aji.即从矩阵的左上角到右下角的主对角线为轴,右上角的元和左下角相对应的元全都是相等的. 从这个矩阵中,很容易知道图中的信息. (1)要判断任意两顶点是否有

图的存储结构及遍历

一.图的存储结构 1.1 邻接矩阵 图的邻接矩阵存储方式是用两个数组来表示图.一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中的边或弧的信息. 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 看一个实例,下图左就是一个无向图. 从上面可以看出,无向图的边数组是一个对称矩阵.所谓对称矩阵就是n阶矩阵的元满足aij = aji.即从矩阵的左上角到右下角的主对角线为轴,右上角的元和左下角相对应的元全都是相等的. 从这个矩阵中,很容易知道图中的信息. (1)要判断任意两顶点是否有

数据结构(五)图---图的存储结构5种

一:图的抽象数据类型 ADT 图(Graph) Data 顶点的有穷非空集合和边的集合 Operation CreateGraph(*G,V,VR):按照顶点集V和边弧集VR的定义构造图G DestroyGraph(*G):图G存在则销毁 LocateVex(G,u):若图G中存在顶点u,则返回图中位置 GetVex(G,v):返回图中顶点v的值 PutVex(G,v,value):将图G中顶点v赋值给value FirstAdjVex(G,*v):返回顶点v的一个邻接顶点,若顶点在G中无邻接顶

数据--第41棵 - 图的存储结构

第41棵 - 图的存储结构 1. 邻接矩阵法 用一维数组存储顶点--描述顶点相关的数据. 用二维数组存储边--描述顶点的边. 设图A = (V,E)是一个有n个顶点的图,图的邻接矩阵为Edge[n][n],则:Edge[i][j] = W,W>0,i和j连接:Edge[i][j] = 0,i == j 或者i和j不链接. 注:W为权值,当需要权值时,取W为1表示结点间连接. 无向图的邻接矩阵是对称的. 有向图的邻接矩阵可能是不对称的. 2. 邻接矩阵法的头结点 记录定点的个数. 记录与顶点相关的

【algo&amp;ds】5.图及其存储结构、遍历

1.什么是图 图表示"多对多"的关系 包含 一组顶点:通常用 V(Vertex)表示顶点集合 一组边:通常用 E(Edge)表示边的集合 边是顶点对:(v,w)∈ E,其中 v,w ∈ V ,v-w 有向边 <v,w> 表示从 v 指向 w 的边(单行线) v→w 不考虑重边和自回路 常见术语 无向图:图中所有的边无所谓方向 有向图:图中的边可能是双向,也可能是单向的,方向是很重要的 权值:给图中每条边赋予的值,可能有各种各样的现实意义 网络:带权值的图 邻接点:有边直接相