图的存储结构
1.邻接矩阵
1.1简介
**图的邻接矩阵存储方式就是用两个数组来表示图,一个一维数组存储图的顶点信息,一个二维数组(邻接矩阵)来存储图中的边或者是弧的关系。
设图G有那个顶点,则邻接矩阵是一个n X n的二维数组。则元素arc[i][j]表示从节点i到节点j的cost或者距离。如果从i->j没有直接的边连着,则可以定义arc[i][j]=65535,或者arc[i][j]=-1;一般的来说对于图的邻接矩阵,如果图是无向图则,主对角线的元素均为0,邻接矩阵关于主对角线对称。如果是有向图则不对称,但是主对角线的元素均为0。
有了这个矩阵,我们就可以知道很多的信息。**
- 任意两点i,j是否有边只要看arc[i][j]是否为65535或者-1,否则元素的值则为边的长度;
- 某一点的出度:对应行不等于65535的元素的个数;
- 某一点的入度:对应列不等于65535的元素的个数;
- 任意两点之间的边的编号:对应的元素值(这里修改为arc[i][j]表示从节点i到节点j的边的编号);
- 任意两点之间的的边的距离:根据4.查出边,然后求出边的长度。
1.2相关代码
定义边
struct Arc
{
int iNo; /*编号*/
int Source; /*起点*/
int Terminal; /*终点*/
int Cost; /*边长*/
}Arc,ArcList[400];
定义图的邻接矩阵
#define POINTNUM 10 /*顶点的个数*/
typedef struct
{
int iPoint, iArc;/*顶点的个数、边的个数*/
int arc[POINTNUM][POINTNUM];/*邻接矩阵*/
}Graph;
邻接矩阵的初始化和赋值
void CreateGraph(Graph *G, ArcList *Topo)
{
for (int i = 0; i < G->iPoint; i++)
for (int j = 0; j < G->iPoint; j++)
G->arc[i][j] = -1; /*初始化元素为-1*/
for (int i = 0; i < G->iArc; i++)
{
int s = Topo[i]->Source;
int t = Topo[i]->Terminal;
G->arc[s][t] = Topo[i]->Cost; /*根据边赋值*/
}
}
2.邻接表
2.1简单说明
**邻接矩阵是一种很好的图的存储结构,但是同时我们发现,对于每个点的出度都比较小的稀疏图,这种图的存储结构对于内存是一种极大的浪费。因为所有的顺序存储结构都是预先分配内,因而会造成存储空间的浪费。因此我们不妨试试链式存储结构。
在这里,我们电灯额信息还是用数组表示,而将点的节点的信息由二维数组更改为链式存储。我们将这种数组与链表相结合的存储的方式称为邻接链表。
邻接表的处理办法是这样的。**
- 图的顶点用一个一维的数组存储,在每个顶点的数组中,还要存一个指向第一个邻接点的指针。
- 图的每个顶点的所有的邻接点构成一个线性表,由于邻接点的个数不定,所以用单链表表示。
2.2相关代码
边表的定义
typedef struct Node
{
int iNo; /*顶点下标*/
int iLength; /*顶点长度*/
struct Node *pNextNode; /*指向下一个地址*/
}Node;
顶点定义
typedef struct Head
{
int iNo; /*顶点下标*/
Node *pFirstNode; /*边表头指针*/
}Head,HeadList[4000];
图的定义
typedef struct
{
HeadList sHead;
int iPoint,iArc;
}Graph;
初始化和赋值
void CreateGraph(Graph *G, ArcList *Topo)
{
for (int i = 0; i < G->iPoint; i++)
{
G->sHead[i].iNo = i;
G->sHead[i].pFirstNode == NULL;
}
for (int i = 0; i < G->iArc; i++)
{
Node* pNode = (Node*)malloc(sizeof(Node));
pNode->iNo = Topo[i]->Terminal;
pNode->iLength = Topo[i]->Cost;
pNode->pNextNode = G->sHead[Topo[i]->Source].pFirstNode;
G->sHead[Topo[i]->Source].pFirstNode = pNode;
}
}
ENd