目录
邻接矩阵
考虑到图是由顶点和边或弧两部分组成,合在一起比较困难,那就自然想到分两个结构来分别存储。
顶点存储:
顶点不分大小、主次,所以用一个一维数组来存储是很不错的选择
边或弧存储:
边或弧由于是顶点与顶点之间的关系,一维搞不定,那就考虑二维数组来存储
邻接矩阵定义:
图的邻接矩阵存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组存储图中的边或弧的信息
网:
在图的术语中,我们提到了网的概念,也就是每条边上带有权的图叫做网。那么这些权值就需要存下来
邻接矩阵存储的代码实现:
typedef char VertexType;//顶点类型应由用户定义
typedef int EdgeType;//边上的权值类型应由用户定义
#define MAXVEX 100//最大顶点树,应由用户定义
#define INFINITY 65535 //用65535来表示无穷
typedef struct {
VertexType vexs[MAXVEX];//顶点表
EdgeType arc[MAXVEX][MAXVEX];//邻接矩阵,可看做边边
int numNodes, numEdges;//图中当前的顶点数和边数
}MGraph;
图的构造:
代码实现:
void CreateMGraph(MGraph* G){
int i,j,k,w;
cout<<"输入顶点数和边数"<<end;
scanf("%d %d",&G->numNodes,&G->numEdges);//输入顶点数和边数
for(int i=0;i<G->numNodes;i++)//读入顶点信息,建立顶点表
scanf("%d",&G->vex[i]);
for(i=0;i<G->numNodes;i++){
for(j=0;j<G->numEdges;j++){
G->arc[i][j]=INFINITY;//邻接矩阵初始化
}
}
for(k=0;k<G->numEdges;k++){
cout<<"输入边上的下标i,下标j和权w"<<endl;
cin>>i>>j>>w;
G->arc[i][j]=w;
G->arc[j][i]=G->arc[i][j];//无向图
}
}
初始化的时间复杂度为O(N^2)
邻接表:
邻接矩阵是不错的一种图存储结构,但是我们也发现,对于边数相对顶点较少的图,这种结构是存在对存储空间的极大浪费的
回忆我们在树中谈存储结构是,讲到了一种孩子表示法,将结点存入数组,并对结点的孩子进行粮食存储,不管有多少个孩子,也不会对空间造成浪费。
同样的思路适用于图的存储:
我们把这种数组与链表相结合的存储方法称为邻接表
邻接表的处理方式如下:
(1)图中顶点用一个一维数组存储,方便较容易读取顶点信息,同时每一个顶点还需要存储一个指向第一个临界点的指针
(2)图中每个顶点vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以用单链表存储,无向图称为顶点vi的边表,有向图称为顶点vi作为弧尾的出边表
图中解析:
data:存储顶点的数据
firstedge:存储指向边表的第一个结点
adjvex:邻接点域,存储某顶点的邻接点在顶点表中的下标
next:存储指向边表下一个结点的指针
逆邻接表:
为了便于确定顶点的入读或以顶点为弧头的弧,我们可以建立一个有向图的逆邻接矩阵,即每个顶点vi都建立一个连接为vi为弧头的表。
带权的网图:
我们可以在便捷点定义中再增加一个weight的数据域,存储权值信息即可
邻接表实现代码:
结构实现:
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 CreatALGraph(GraphAdjList *G)
{
EdgeNode *e;
cout<<"输入顶点数和边数"<<endl;
cin>>G->numNodes>>G->numEdges;//输入顶点数和边数
for(int i=0;i<G->numNodes;i++)//读入顶点信息,建立顶点表
{
cin>>G->adjList[i].data;//输入顶点信息
G->adjList[i].firstedge=NULL;//将边表置为空表
}
for(int k=0;k<G->numEdges;k++)//建立边表
{
cout<<"输入边上的顶点序号"<<endl;
cin>>i>>j;
e=(EdgeNode*)malloc(sizeof(EdgeNode));//向内存申请空间,生成边表结点
e->adjvex=j;//邻接序号为j
e->next=G->adjList[i].firstedge;//将e的指针指向当前顶点指向的结点
G->adjList[i].fristedge=e;
e=(EdgeNode*)malloc(sizeof(EdgeNode));
e->adjvex=i;//邻接序号为i
e->next=G->adjList[j].firstedge;
G->adjList[j].fristedge=e;
}