但行好事,莫问前程
无向图的邻接矩阵:
邻接矩阵(Adjacency Matrix)是表示顶点之间相邻关系的矩阵。
图例:
算法实现该例子
#define MaxInt 1000000 //表示极大值,即 ∞
#define MVNum 100 //最大顶点数
typedef struct{
int arcs[MVNum][MVNum]; //邻接矩阵
int vexnum,arcnum; //图的当前点数和边数
}AMGraph; //构建图的属性
void CreateUDN(AMGraph &G){
//采用邻接矩阵表示法,创建无向网G
cout<<"输出总顶点数以及边数"<<endl;
cin>>G.vexnum>>G.arcnum; //输入总顶点数,总边数
for(int i = 0; i<G.vexnum;++i) //初始化邻接矩阵,边的权值均置为极大值
for(int j = 0; j<G.vexnum;++j)
G.arcs[i][j] = MaxInt;
for(int k = 0; k<G.arcnum;++k){ //构造邻接矩阵
int v1,v2,w;
cout<<"前顶点:";
cin>>v1;
cout<<"后顶点:";
cin>>v2;
cout<<"值:";
cin>>w; //输入边上的权值
if(v1 > G.vexnum) //v1,v2的值不能大于顶点数,否者改变值为-1
v1 = -1;
if(v2 > G.vexnum)
v2 = -1;
G.arcs[v1][v2] = w; //边<v1, v2>的权值置为w
G.arcs[v2][v1] = G.arcs[v1][v2]; //置<v1, v2>的对称边<v2, v1>的权值为w
}
for(int n=0;n<G.vexnum;n++){
for(int m=0;m<G.vexnum;m++)
cout<<G.arcs[n][m]<<"\t";
cout<<"\n";
} // 输出矩阵;
return;
}//CreateUDN
输入图例中的值,测试结果为:
优点: 容易实现图的操作,如:求某顶点的度、判断顶点之间是否有边、找顶点的邻接点等等。
缺点 n个顶点需要n*n个单元存储边;空间效率为O(n2)。 对稀疏图而言尤其浪费空间。
无向图的邻接表
邻接表,存储方法跟树的孩子链表示法相类似,是一种顺序分配和链式分配相结合的存储结构。如这个表头结点所对应的顶点存在相邻顶点,则把相邻顶点依次存放于表头结点所指向的单向链表中。
该程序实现
算法实现:
每个顶点与边的存储方式:
顶点节点定义
#define MVNum 100 //最大顶点数
typedef struct ArcNode{ //边结点
int adjvex; //该边所指向的顶点的位置
struct ArcNode * nextarc; //指向下一条边的指针
int info; //和边相关的信息
}ArcNode;
边节点定义
typedef struct VNode{
VertexType data; //顶点信息
ArcNode * firstarc; //指向第一条依附该顶点的边的指针
}VNode, AdjList[MVNum]; //AdjList表示邻接表类型
表定义
typedef struct{
AdjList vertices; //邻接表
int vexnum, arcnum; //图的当前顶点数和边数
}ALGraph;
int CreateUDG(ALGraph &G){
//采用邻接表表示法,创建无向图G
cout<<"输入总顶点和总边数";
cin>>G.vexnum>>G.arcnum; //输入总顶点数,总边数
for(int i = 1; i<=G.vexnum; ++i){ //输入各点,构造表头结点表
G.vertices[i].firstarc=NULL; //初始化表头结点的指针域为NULL
}
for(int k = 0; k<G.arcnum;++k){ //输入各边,构造邻接表
int i=-1,j=-1;
int w;
while(i==-1 || j==-1){
cout<<"输入边依赖的两个顶点和值:";
cin>>i>>j>>w; //输入一条边依附的两个顶点以及值
i = i <= G.vexnum? i:-1;
j = j <= G.vexnum? j:-1;
}
ArcNode *p1=new ArcNode; //生成一个新的边结点*p1
p1->adjvex = j; //邻接点序号为j
p1->nextarc= G.vertices[i].firstarc;
p1->info = w;
G.vertices[i].firstarc=p1;
//将新结点*p1插入顶点vi的边表头部
ArcNode *p2=new ArcNode; //生成另一个对称的新的边结点*p2
p2->adjvex=i; //邻接点序号为i
p2->nextarc= G.vertices[j].firstarc;
p2->info = w;
G.vertices[j].firstarc=p2;
//将新结点*p2插入顶点vj的边表头部
}
for(i=1;i <= G.vexnum;i++){ //遍历
ArcNode *an=G.vertices[i].firstarc;
cout<<"第"<<i<<"个结点为:";
while(NULL != an){
cout<<"->"<<an->adjvex<<","<<(int)an->info<<'\t';
an = an->nextarc;
}
cout<<endl;
}
}
return 1;
}//CreateUDG
*/
测试结果:
优点:
空间效率高,容易寻找顶点的邻接点;
缺点:
判断两顶点间是否有边或弧,需搜索两结点对应的单链表,没有邻接矩阵方便。