图-邻接矩阵

自然界中有很多事物可以用图来表示其间的关系,在电脑中可以通过处理图来解决实际问题,但是问题来了,

如何将实际问题转化为图可以表示的形式?
如何在计算机中存储图,有几种方式?
如果图只是体现了节点与节点间是否有关系,那么如果节点本身的内容就很重要,怎么存储?

第一个问题-图的输入

要想在计算机中创建一个图的数据结构,就得先把现有的图输入进去,那么现有的图用现在的按行输入的方式怎么表示呢?
下面是POJ中2386题对图的表示,其中10和12为下面图的长和宽
10 12         
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
除了用上面这中直接的表示,也可以将问题用画图的方式呈现在纸上,
    然后得出有多少个节点,有多少条边,那些节点之间有联系,,这个联系是单向的还是双向的,这个联系有没有权重,如果有的话,每个节点之间的权重是多少,
        知道上面这些问题后,就可以按照上面的这些关键信息,组织代码,确定先输入什么再输入什么,确定怎么输入才能完整的记录一个图。

图的第一种存储方式-邻接矩阵

邻接矩阵的表示
    邻接矩阵就像一个坐标轴上存在的点和线,纵轴和横轴是一样的数据,即用来表示节点数据的数组,如果某个点和另一个点有关系,就从该点的纵轴引出一条线,从另一点所在的横轴引出一条线,在两条线的交点处做上标记或者写上权重,这样就可以用这个数据结构表示自然界的图了。

用邻接矩阵创建一个图

数据结构
    用来存储节点数据的数组
        (节点可以有多种类型)
        (可以不止用数组存储,用其他数据结构也可,只要能保存完整的必须的节点数据)
    存储图的节点数量和边的数量的变量
        (在遍历时会用的到,用来确定遍历什么时候结束)
    一个二维数组
        (也就是邻接矩阵,用来表示节点与节点之间的关系,即是否相连,或如果相连的话,其间的权重是多少)
不同的输入方式
    第一种
        输入节点个数,边数
        输入所有的节点(存入数组,必须要各不相同,否则会变复杂)
        输入一个节点与另一个节点或者加上权重(表示两个节点相连,节点的先后也可以代表方向)
            (这第三步要输入节点之间的关系或权重依旧需要遍历数组,找到节点的位置,以便在矩阵中定位)
    第二种
        输入节点个数,边数(有了节点个数其实就能创建一个空白的邻接矩阵了)
        输入一个节点和另一个节点或者加上权重
            循环知道所有关系输入完成
        (问题:一个节点可能与多个节点相连,那么在输入该节点存入数组后,再次输入需要遍历一遍数组,以查看该节点是否已经存在,
            如果不想遍历的话,就需要用一种不允许重复的数据结构存储节点数据,这种数据结构本身使用就是需要代价的)
    第三种
        输入一个节点和另一个节点或者加上权重
        循环上面的过程直到输入停止条件结束
            (节点个数和边数可以由上面的输入得知)
    #可见在输入时做的工作越多越详细,代码越好写,越简单,而输入越接近图,没有自己的提取和总结的话,会比较麻烦,代码需要进行规范的地方越多
    #不同的输入方式有不同的创建代码
第一种输入方式创建邻接矩阵
    这里是第一种输入方式的图的创建代码(无向图带权重):
        #include <iostream>
        #define MAXNUM   100

        using namespace std;

        typedef char VexType;
        typedef int ArcType;
        typedef struct{
            VexType vex[MAXNUM];
            ArcType arc[MAXNUM][MAXNUM];
            int point,line;
        }AMGraph;

        int CreateAM(AMGraph &G)
        {
            cin>>G.point>>G.line;//输入节点数和边数

            for(int i =0;i<G.point;i++)  //输入节点数据
            {
                cin>>G.vex[i];
            }
            for(int x =0;x<G.point;x++)
            {
                for(int y =0;y<G.point;y++)
                {
                    G.arc[x][y]= -1;   //初始化邻接矩阵
                }
            }
            for(int k =0;k<G.line;k++)
            {
                VexType v1,v2;
                int w;
                cin>>v1>>v2>>w;  //输入两个节点和权重
                int p_x,p_y;
                for(int q =0;q<G.point;q++)  //找到节点在数组中的位置
                {
                    if(G.vex[q] == v1)
                        p_x = q;
                }
                for(int r =0;r<G.point;r++)
                {
                    if(G.vex[r] == v2)
                        p_y = r;
                }
                G.arc[p_x][p_y] =w;
                G.arc[p_y][p_x]= G.arc[p_x][p_y]; //无向图是对称的
            }

        }
        int main()
        {
            AMGraph g;
            CreateAM(g);
        }
    上面的代码是针对无向图带权重的
        将权重设置为1即可表示无向图
        修改对称就可以表示有向图带权重
        将权重设置为1并修改对称就可以表示有向图不带权重
    # 修改typedef后的数据类型就可以存储不同类型的节点数据

    如果是第二种输入方式,就要边输入边创建数组,边判断数组中是否已经存在该节点,还要同时在邻接矩阵中设置好权重或者节点之间的关系,由于有节点个数和边数还是比较方便的。
邻接矩阵的特点
    可以扩展存储节点数据的数据结构,使之可以完整的存储节点数据
    适合稠密图,如果是稀疏图的话,对于一个大的邻接矩阵可能会有很多没用的遍历,也会浪费较多的空间
    如果是稀疏图,无向图的话,可以压缩存储,因为无向图是对称的
    增加或者删除节点不方便,要修改整个数组和邻接矩阵
    很容易判断两个节点是否相连以及其权重,因为二维数组只要知道位置可以随机访问
    计算各个节点的度也很方便,计算每行或者每列的总和即可
    边数可以在一开始输入,但是创建完邻接矩阵后,却不容易从该邻接矩阵判断出边数是多少,得整个遍历
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值