一:图的基本术语:
1.无向图:图G中的每条边都是无方向的
2.有向图:图G中的每条边都是有方向的;
3.完全图:图G任意两个顶点都有一条边相连接;
4.有向完全图:若n个顶点的有向图有n(n-1)条边, 称为有向完全图
5.简单路径:路径上各顶点 v1,v2,...,vm 均不互相重复
6.回路(环):路径上第一个顶点 v1 与最后一个顶点vm 重合
7.连通图:图中任意一对顶点都是连通的, 则称此图是连通图
8.强连通图:有向图中, 若对于每一对顶点vi和vj, 都存在一条从vi到vj和从vj到vi的路径, 则称此图是强连通图。
9.顶点的度:顶点V的度 TD(v) = ID(v) + OD(v) ID表示入度 OD表示出度
10.生成树: 一个连通图的生成树是一个极小连通子图,它含有图中全部顶点,但只有足以构成一棵树的n-1条边
二.图的存储结构:
1.邻接矩阵存储
(1)无向图(有向也一样,不对称而已)
A[i][j]=1表示顶点Vi和Vj之间有边相连
(2)带权图(有向无向一样理解)
(3)存储结构:
#define INFINITY INT_MAX // 最大值∞
#define MAX_VERTEX_NUM 20 // 最大顶点个数
typedef enum {DG, DN, UDG, UDN} GraphKind;
//图类型(有向图/网,无向图/网)
typedef struct ArcCell {//弧信息
VRType adj; // 顶点的关系类型。对无权图,用1或0表示相邻否;对带权图,则为权值类型,adj表示权值
InfoType *info; // 指向该弧相关信息的指针(如果有其他信息,则指向它)
} ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct {
VertexType vexs[MAX_VERTEX_NUM]; // 描述顶点的数组
AdjMatrix arcs; // 邻接矩阵
int vexnum, arcnum; // 图的当前顶点数和弧(边)数
GraphKind kind; // 图的种类标志
} MGraph;
以创建无向网图为例来理解这种结构:
Status CreateUDN(MGraph &G){
sacnf( &G.vexnum, &G.arcnum, &IncInfo);
for(i=0;i<G.vexnum;++i) scanf(&G.vexs[i]); //构造顶点向量
for(i=0;i<G.vexnum;++i) //初始化邻接矩阵
for(j=0;j<G.vexnum;++j) G.arcs[i][j]={INFINITY,NULL}; // {adj,info}
for(k=0;k<G.arcnum;++k){ //构造邻接矩阵
scanf(&v1,&v2,&w); //输入一条边依附的顶点及权值
i=LocateVex(G,v1);j=LocateVex(G,v2); //找到v1和v2在G中位置
G.arcs[i][j].adj=w;//弧<v1,v2>的权值
if (IncInfo) Input (*G.arcs[i][j].info);//如果IncInfo不为0,则就输入弧相关信息
G.arcs[j][i]=G.arcs[i][j]; //置<v1,v2>的对称弧<v2,v1> }
return OK;
}//CreateUDN
2.邻接表存储:
对每个顶点vi 建立一个单链表,把与vi 有关联的边的信息(即度或出度边)链接起来,表中每个结点都设为3个域;
每个单链表还应当附设一个头结点(设为2个域),存vi信息;每个单链表的头结点另外用顺序存储结构存储。
例子:
注:因为读入的结点连接顺序不一样,所以邻接表不一样!(有向图同理)
typedef struct ArcNode
{
int adjvex;//该弧邻接到的顶点的位置
InfoType *info;//该弧相关信息的指针(比如说可以使带权图的权值)
struct ArcNode* nextArc;
}ArcNode;
typedef struct VNode
{
VertexType data;//顶点的数据信息
ArcNode* firstArc;//指向第一个依附该结点的弧
}VNode,AdjList[MAX_VERTEX_NUM];//要线性的顺序存储组合在一起,所以采用数组;
typedef struct ALGraph
{
AdjList vertices;
int verNum,arcNum;//图的定点数和弧树
int kind;//图的种类
}ALGraph;
也是以建立邻接表图为例:
void CreateUDN(ALGraph &ga)
{
ArcNode *p;
char name1[40],name2[40];
int i,j,k;
double w;
printf("请输入顶点数和弧数:");
scanf("%d%d",&ga.vexNum,&ga.arcNum);
printf("请依次输入顶点名:\n");
for(i=0;i<ga.vexNum;i++)
{
scanf("%s",ga.vertices[i].data);
ga.vertices[i].firstarc=NULL;
}
for(k=0;k<ga.arcNum;k++)
{
printf("请输入相邻的两个定点和权值:");
scanf("%s%s%lf",name1,name2,&w);
i=LocateVex(ga,name1);
j=LocateVex(ga,name2);
p=new ArcNode;
p->adjvex=j;
p->adj=w;
p->nextarc=ga.vertices[i].firstarc;//先进后出式插入
ga.vertices[i].firstarc=p;
}
}