学习数据结构的一些随记:
1、图的若干定义
图G由顶点的集合V和边的集合E组成,即G=(V,E)。
每一条边就是一个点对(v,w),有时边也称作弧。若点对有序,则称为有向图,反之称为无向图。
所谓路径是指一个点的序列,路径的长是指边的数目。
一个顶点到它自身的边称作环,我们所讨论的图一般都是无环的。
如果在无向图中每一个顶点到每个其他顶点都存在一条路径,则称该无向图是连通的。
具有这样性质的有向图是强连通的。若有向图非强连通,但其基础图是强连通,则称该有向图是弱连通的。
完全图是每对顶点都存在一条边的图。
图应用的典型例子有:航空系统、城市交通系统等。
2、图的表示方法
2.1 邻接矩阵
基本思想就是用两个结构来分别表示图中的顶点和边(或弧),也可以算是模块化思想吧?
顶点可以用一个一维数组表示,边用一个二维数组表示。我们可以用0表示两顶点间存在边,1表示两顶点间不存在边,或者用相应边的权值来填充二维数组(矩阵)。
[CODE=cplusplus]//邻接矩阵创建_CreateALGraph
#include "stdio.h"
#include "stdlib.h"
#include "io.h"
#include "math.h"
#include "time.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXVEX 100 /* 最大顶点数,应由用户定义 */
#define INFINITY 65535
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef char VertexType; /* 顶点类型应由用户定义 */
typedef int EdgeType; /* 边上的权值类型应由用户定义 */
typedef struct
{
VertexType vexs[MAXVEX]; /* 顶点表 */
EdgeType arc[MAXVEX][MAXVEX];/* 邻接矩阵,可看作边表 */
int numNodes, numEdges; /* 图中当前的顶点数和边数 */
}MGraph;
/* 建立无向网图的邻接矩阵表示 */
void CreateMGraph(MGraph *G)
{
int i,j,k,w;
printf("输入顶点数和边数:\n");
scanf("%d,%d",&G->numNodes,&G->numEdges); /* 输入顶点数和边数 */
for(i = 0;i
scanf(&G->vexs[i]);
for(i = 0;i
for(j = 0;j
G->arc[i][j]=INFINITY; /* 邻接矩阵初始化 */
for(k = 0;k
{
printf("输入边(vi,vj)上的下标i,下标j和权w:\n");
scanf("%d,%d,%d",&i,&j,&w); /* 输入边(vi,vj)上的权w */
G->arc[i][j]=w;
G->arc[j][i]= G->arc[i][j]; /* 因为是无向图,矩阵对称 */
}
}
int main(void)
{
MGraph G;
CreateMGraph(&G);
return 0;
}
[/CODE]
2.2 邻接表
试想如果图中的边很少,那势必会造成表示边的二维数组中存储空间的极大浪费,这时我们可以考虑用链表结构来存储边,即我们所说的邻接表。
一维数组存储顶点,其中每个数据元素除了存储顶点,还需要存储指向第一个邻接点的指针,以便于查找该顶点的边信息。
每个顶点的邻接点构成一个线性表。
对于有向图分为以顶点为弧尾来存储边表(方便求顶点的出度)和以顶点为弧头来存储边表(方便求顶点的入度,逆邻接表)。
对于带权值的图,只需在边表节点定义中再增加一个表示权值的数据域来存储权值信息即可。
[CODE=cplusplus]
//邻接表创建_CreateALGraph
#include "stdio.h"
#include "stdlib.h"
#include "io.h"
#include "math.h"
#include "time.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXVEX 100 /* 最大顶点数,应由用户定义 */
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef char VertexType; /* 顶点类型应由用户定义 */
typedef int EdgeType; /* 边上的权值类型应由用户定义 */
typedef struct EdgeNode /* 边表结点 */
{
int adjvex; /* 邻接点域,存储该顶点对应的下标 */
EdgeType info; /* 用于存储权值,对于非网图可以不需要 */
struct EdgeNode *next; /* 链域,指向下一个邻接点 */
}EdgeNode;
typedef struct VertexNode /* 顶点表结点 */
{
VertexType data; /* 顶点域,存储顶点信息 */
EdgeNode *firstedge;/* 边表头指针 */
}VertexNode, AdjList[MAXVEX];
typedef struct
{
AdjList adjList;
int numNodes,numEdges; /* 图中当前顶点数和边数 */
}GraphAdjList;
/* 建立图的邻接表结构 */
void CreateALGraph(GraphAdjList *G)
{
int i,j,k;
EdgeNode *e;
printf("输入顶点数和边数:\n");
scanf("%d,%d",&G->numNodes,&G->numEdges); /* 输入顶点数和边数 */
for(i = 0;i < G->numNodes;i++) /* 读入顶点信息,建立顶点表 */
{
scanf(&G->adjList[i].data); /* 输入顶点信息 */
G->adjList[i].firstedge=NULL; /* 将边表置为空表 */
}
for(k = 0;k < G->numEdges;k++)/* 建立边表 */
{
printf("输入边(vi,vj)上的顶点序号:\n");
scanf("%d,%d",&i,&j); /* 输入边(vi,vj)上的顶点序号 */
e=(EdgeNode *)malloc(sizeof(EdgeNode)); /* 向内存申请空间,生成边表结点 */
e->adjvex=j; /* 邻接序号为j */
e->next=G->adjList[i].firstedge; /* 将e的指针指向当前顶点上指向的结点 */
G->adjList[i].firstedge=e; /* 将当前顶点的指针指向e */
e=(EdgeNode *)malloc(sizeof(EdgeNode)); /* 向内存申请空间,生成边表结点 */
e->adjvex=i; /* 邻接序号为i */
e->next=G->adjList[j].firstedge; /* 将e的指针指向当前顶点上指向的结点 */
G->adjList[j].firstedge=e; /* 将当前顶点的指针指向e */
}
}
int main(void)
{
GraphAdjList G;
CreateALGraph(&G);
return 0;
}
[/CODE]
2.3 十字链表
将邻接表和逆邻接表结合起来。
[CODE=cplusplus]
typedef struct VertexNode/* 顶点表结点 */
{
VertexType data;
EdgeNode *firsrin;//指向该顶点入边表中的第一个节点
EdgeNode *firstout; //指向该顶点出边表中的第一个节点
} VertexNode;
typedef struct EdgeNode /* 边表结点 */
{
int headvex; /* 弧终点在顶点表中对应的下标 */
int tailvex; /* 弧起点在顶点表中对应的下标 */
headlink; /* 入边表指针域 */
taillink; /* 边表指针域 */
}EdgeNode;
[/CODE]
2.4 邻接多重表
邻接多重表是对邻接表针对操作边不易的一种改进,在邻接表中,一条边需用两个节点表示;而在邻接多重表中,一条边用一个节点表示。
[CODE=cplusplus]
已经有(0)位网友发表了评论,你也评一评吧!
原创文章如转载,请注明:转载自Eddy Blog
原文地址:http://www.rrgod.com/skill/833.html 欢迎订阅Eddy Blog。