1.定义:
2.特点:
无向图的邻接矩阵一定是对称的,而有向图的邻接矩阵不一定对称。因此,用邻接矩阵来表示一个具有n个顶点的有向图时需要n^2个单元来存储邻接矩阵;对有n个顶点的无向图则只存入上(下)三角阵中剔除了左上右下对角线上的0元素后剩余的元素,故只需1+2+...+(n-1)=n(n-1)/2个单元。
无向图邻接矩阵的第i行(或第i列)非零元素的个数正好是第i个顶点的度。
3.表示法:
在图的邻接矩阵表示法中:
① 用邻接矩阵表示顶点间的相邻关系
② 用一个顺序表来存储顶点信息
图的矩阵
设G=(V,E)是具有n个顶点的图,则G的邻接矩阵是具有如下性质的n阶方阵:
【例】
网络矩阵
若G是网络,则邻接矩阵可定义为:
其中:
w ij 表示边上的权值;
∞表示一个计算机允许的、大于所有边上权值的数。
【例】下面带权图的两种邻接矩阵分别为A 3 和A 4 。
图的邻接矩阵存储结构形式说明
#define MaxVertexNum l00 //最大顶点数,应由用户定义
typedef char VertexType; //顶点类型应由用户定义
typedef int EdgeType; //边上的权值类型应由用户定义
typedef struct
{ VextexType vexs[MaxVertexNum] //顶点表
EdeType edges[MaxVertexNum][MaxVertexNum];//邻接矩阵,可看作边表
int n,e; //图中当前的顶点数和边数
}MGragh;
注意:
④邻接矩阵表示法的空间复杂度S(n)=0(n 2 )。
⑤建立无向网络的算法。
void CreateMGraph(MGraph *G){
//建立无向网的邻接矩阵表示
int i,j,k,w;
scanf("%d%d",&G->n,&G->e); //输入顶点数和边数
for(i = 0;i < n;i++) //读入顶点信息,建立顶点表
{ G->vexs=getchar(); }
for(i = 0;i < G->n;i++)
{ for(j = 0;j <G->n;j++)
{ G->edges[i][j] = 0; //邻接矩阵初始化
}
}
for(k = 0;k < G->e;k++)
{//读入e条边,建立邻接矩阵
scanf("%d%d%d",&i,&j,&w); //输入边(v i ,v j )上的权w
G->edges[i][j]=w;
G->edges[j][i]=w;
}
}//CreateMGraph
该算法的执行时间是0(n+n 2 +e)。由于e
根据图的定义可知,图的逻辑结构分为两部分:V和E的集合。因此,用一个一维数组存放图中所有顶点数据;用一个二维数组存放顶点间关系(边或弧)的数据,称这个二维数组为邻接矩阵。邻接矩阵又分为有向图邻接矩阵和无向图邻接矩阵。
Matlab表达N=4;//图中的节点数目dag=zeros(N,N);//邻接矩阵初始化,值均为0C=1;S=2;R=3;W=4;//制定各节点编号dag(C,[RS])=1;//有两条有向边:C->R,C->Sdag(R,W)=1;//有向边:R->Wdag(S,W)=1;//有向边:S->W
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <queue> using namespace std; #define MAX 0x1f1f1f1f #define N 200 bool visit[N]; typedef char VerterType[20]; typedef struct tu { VerterType vexs[N];//顶点数组 int arc[N][N];//邻接矩阵数组 int numpoint,numedge; //图的顶点数和边数 int kind;//图的类型 } graph; //1、确定顶点的位置 int locates(graph &head,VerterType a) { int i,j; for(i=0; i<head.numpoint; i++) { if(strcmp(head.vexs[i],a)==0) { j=i; break; } } return j; } //2、创建图 void graphcreate(graph &head) { int i,j,k; printf("输入顶点数和边数,图的类型:1.无向图,2.无向网,3.有向图,4.有向网 "); cin>>head.numpoint>>head.numedge>>head.kind; printf("输入定点数组: "); for(i=0; i<head.numpoint; i++) { cin>>head.vexs[i]; } for(i=0; i<head.numpoint; i++) { for(j=0; j<head.numpoint; j++) { head.arc[i][j]=MAX; } } VerterType a,b; int quan; if(head.kind%2==1) printf("请输入弧尾、弧头: "); else printf("请输入弧尾、弧头和权值: "); if(head.kind==1) { for(i=0; i<head.numedge; i++) { cin>>a>>b; int s1=locates(head,a),s2=locates(head,b); head.arc[s1][s2]=1; head.arc[s2][s1]=1; } } else if(head.kind==2) { for(i=0; i<head.numedge; i++) { cin>>a>>b>>quan; int s1=locates(head,a),s2=locates(head,b); head.arc[s1][s2]=quan; head.arc[s2][s1]=quan; } } else if(head.kind==3) { for(i=0; i<head.numedge; i++) { cin>>a>>b; int s1=locates(head,a),s2=locates(head,b); head.arc[s1][s2]=1; } } else { for(i=0; i<head.numedge; i++) { cin>>a>>b>>quan; int s1=locates(head,a),s2=locates(head,b); head.arc[s1][s2]=quan; } } } //3.遍历整个邻接矩阵 void printGraph(graph &g) { int i, j; for(i = 0; i < g.numpoint; i++) { for(j = 0; j < g.numpoint; j++) { printf("%d", g.arc[i][j]); if(j!=g.numpoint-1) printf(" "); else printf(" "); } } } //4、两个顶点是否存在边。 void find(VerterType a,VerterType b,graph &p) { int i,s1,s2; s1=locates(p,a); s2=locates(p,b); if(p.arc[s1][s2]<MAX&&p.arc[s1][s2]>0) { if(p.kind%2==1)cout<<"yes"<<endl; else { cout<<"yes"<<endl; cout<<a<<"--"<<b<<"的度为:"<<p.arc[s1][s2]<<endl; } } else cout<<"no"<<endl; } //5.查找一个定点的度。(有向图输出入度加出度之和) void findextent(graph &p,VerterType a) { int n,i,j,k,sum=0; if(p.kind<=2) { k=locates(p,a); for(i=0; i<p.numpoint; i++) { if(p.arc[k][i]!=MAX&&p.arc[k][i]!=0) sum++; } cout<<"度为:"<<sum<<endl; } else { k=locates(p,a); for(i=0; i<p.numpoint; i++) { if(p.arc[k][i]!=MAX&&p.arc[k][i]!=0) sum++; if(p.arc[i][k]!=MAX&&p.arc[i][k]!=0) sum++; } cout<<"度为:"<<sum<<endl; } } int maxx; void DFS(graph &p,int i) { maxx++; int j; visit[i]=true; cout<<p.vexs[i]; if(maxx!=p.numpoint) cout<<" "; else cout<<endl; for(j=0; j<p.numpoint; j++) { if(p.arc[i][j]>0&&p.arc[i][j]<MAX&&visit[j]==false) { DFS(p,j); } } } void DFSTraverse(graph g) { int i; memset(visit,false,sizeof(visit)); for(i = 0; i < g.numpoint; i++) { if(!visit[i]) { DFS(g,i); } } } void BFS(graph &p) { int i,j; int sum=0; queue<int>q; memset(visit,false,sizeof(visit)); for(i=0; i<p.numpoint; i++) { if(!visit[i]) { visit[i]=true; cout<<p.vexs[i]; sum++; if(sum!=p.numpoint) cout<<" "; else cout<<endl; q.push(i); while(!q.empty()) { int m; m=q.front(); q.pop(); for(j=0; j<p.numpoint; j++) { if(p.arc[m][j]>0&&p.arc[m][j]<MAX&&!visit[j]) { visit[j]=true; cout<<p.vexs[j]; sum++; if(sum!=p.numpoint) cout<<" "; else cout<<endl; q.push(j); } } } } } } int main() { graph head; VerterType a,b; int n; cin>>n; while(n--) { maxx=0; graphcreate(head); printf("输出链接矩阵: "); printGraph(head); printf("请输入两个顶点: "); cin>>a>>b; printf("判断两顶点之间是否存在边: "); find(a,b,head); printf("请输入一个顶点: "); cin>>a; printf("它的度为: "); findextent(head,a); printf("深度优先搜索遍历: "); DFSTraverse(head); printf("广度优先搜索遍历: "); BFS(head); } return 0; }
详细解读代码便可分析出相应的知识点了。