码迷,mamicode.com
首页 > 其他好文 > 详细

数据结构之图的邻接矩阵

时间:2015-01-22 10:51:04      阅读:347      评论:0      收藏:0      [点我收藏+]

标签:

1.定义:

邻接矩阵(Adjacency Matrix):是表示顶点之间相邻关系的矩阵。设G=(V,E)是一个图,其中V={v1,v2,…,vn}。G的邻接矩阵是一个具有下列性质的n阶方阵:
①对无向图而言,邻接矩阵一定是对称的,而且对角线一定为零(在此仅讨论无向简单图),有向图则不一定如此。
②在无向图中,任一顶点i的度为第i列所有元素的和,在有向图中顶点i的出度为第i行所有元素的和,而入度为第i列所有元素的和。
③用邻接矩阵法表示图共需要n^2个空间,由于无向图的邻接矩阵一定具有对称关系,所以扣除对角线为零外,仅需要存储上三角形或下三角形的数据即可,因此仅需要n(n-1)/2个空间。
 
2.特点:
无向图的邻接矩阵一定是对称的,而有向图的邻接矩阵不一定对称。因此,用邻接矩阵来表示一个具有n个顶点的有向图时需要n^2个单元来存储邻接矩阵;对有n个顶点的无向图则只存入上(下)三角阵中剔除了左上右下对角线上的0元素后剩余的元素,故只需1+2+...+(n-1)=n(n-1)/2个单元。
无向图邻接矩阵的第i行(或第i列)非零元素的个数正好是第i个顶点的度。
有向图邻接矩阵中第i行非零元素的个数为第i个顶点的出度,第i列非零元素的个数为第i个顶点的入度,第i个顶点的度为第i行与第i列非零元素个数之和。
用邻接矩阵表示图,很容易确定图中任意两个顶点是否有边相连。
3.表示法:
在图的邻接矩阵表示法中:
① 用邻接矩阵表示顶点间的相邻关系
② 用一个顺序表来存储顶点信息
图的矩阵
设G=(V,E)是具有n个顶点的图,则G的邻接矩阵是具有如下性质的n阶方阵:
技术分享
 
【例】
下图中无向图G 5 和有向图G 6 的邻接矩阵分别为A l 和A 2 。
技术分享
 
网络矩阵
若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;
注意:
① 在简单应用中,可直接用二维数组作为图的邻接矩阵(顶点表及顶点数等均可省略)。
② 当邻接矩阵中的元素仅表示相应的边是否存在时,EdgeTyPe可定义为值为0和1的枚举类型
无向图的邻接矩阵对称矩阵,对规模特大的邻接矩阵可压缩存储。
④邻接矩阵表示法的空间复杂度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.有向网\n");
    cin>>head.numpoint>>head.numedge>>head.kind;
    printf("输入定点数组:\n");
    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("请输入弧尾、弧头:\n");
    else
        printf("请输入弧尾、弧头和权值:\n");
    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("\n");
        }
    }
}
//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("输出链接矩阵:\n");
        printGraph(head);
        printf("请输入两个顶点:\n");
        cin>>a>>b;
        printf("判断两顶点之间是否存在边:\n");
        find(a,b,head);
        printf("请输入一个顶点:\n");
        cin>>a;
        printf("它的度为:\n");
        findextent(head,a);
        printf("深度优先搜索遍历:\n");
        DFSTraverse(head);
        printf("广度优先搜索遍历:\n");
        BFS(head);
    }
    return 0;
}

详细解读代码便可分析出相应的知识点了。

 

数据结构之图的邻接矩阵

标签:

原文地址:http://www.cnblogs.com/famousli/p/4240774.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!