zoukankan      html  css  js  c++  java
  • 图的存储与实现(一),使用邻接矩阵

    一、实现思想

    图的邻接矩阵表示法,也叫数组表示法。用一个一维数组存储图中的顶点,用一个二维数组存储图中的边,即各个顶点直接的边的关系,这个二维数组就叫「邻接矩阵」。

    不用代码的话,我们都比较熟悉,图的深度遍历和广度遍历。但是用代码怎么实现,这就要考虑存储一个图了,这个正是本博客的重点。




    设图G=(V,E),有n个顶点,则邻接矩阵是一个 n X n的二维数组。V代表一个点集,E代表一个边集。
    • 对于非网图(没有权值的有向、无向图)
                     = = 1 若(vi,vj) 属于 E
      edge[i][j]
                     = = 0 否则

    这条公式很精辟,因为概括地很好,既包括了有向图,也包括了无向图。其实本质上,我们在置1的时候,考虑的是连通性,如果某个点可以到另一个点,那么二维数组的某个位置就可以置1了。



    • 对于网图(有权值的有向、无向图)

                   = w(ij) 若(vi,vj)属于 E。w(ij)代表某条边的权值

    edge[i][j] = 0 若 i = j

                   = ∞ 否则



    二、实现图

    这里以无向图,不带权值为例子

    • 无向图的深度遍历
    1. 从二维数组的角度来看,我觉得深度遍历的妙处在于,会跳下去。找到一个点之后,顺着这个点往下跳。
    2. 里面用到了递归,跳不下去了,就开始返回。


    • 无向图的广度遍历
    1. 里面用到了「队列」
    2. 从二维数组的角度来看,找到某一行之后,我就扫描完这一行再走。根据队列再找下一行。


    代码实现

    这个代码是无向非网图的例子。

    1. 类的结构
    const int MaxSize = 10;//简单起见,矩阵不要太大
    int visited[MaxSize];//记录点是否被访问过
    
    template <typename DataType>
    class MGraphy
    {
    public:
        MGraphy(DataType a[], int n, int e); //构造函数
        ~MGraphy();
        void DFTraverse(int v); //深度搜索
        void BFTraverse(int v); //广度搜索
    private:
        DataType vertex[MaxSize];   //存放点的数组
        int edge[MaxSize][MaxSize]; //存放图的二维数组
        int vertexNum, edgeNum;     //图的顶点数和边数
    };
    
    1. 构造函数
    template <typename DataType>
    MGraphy<DataType>::MGraphy(DataType a[], int n, int e)
    {
        vertexNum = n;
        edgeNum = e;
        for (int i = 0; i < vertexNum; i++) //存储顶点
            vertex[i] = a[i];
        for (int i = 0; i < vertexNum; i++) //初始化邻接矩阵,即二维数组
            for (int j = 0; j < vertexNum; j++)
                edge[i][j] = 0;
        for (int i = 0; i < MaxSize; i++) //初始化访问标志数组
            visited[i] = 0;
        for (int i = 0; i < edgeNum; i++) //依次输入每一条边
        {
            int m, n;
            cin >> m >> n;  //输入边依附的两个顶点的编号
            edge[m][n] = 1; //置边标志
            edge[n][m] = 1;
        }
    }
    
    1. 深搜
    
    template <typename DataType>
    void MGraphy<DataType>::DFTraverse(int v)
    {
        cout << vertex[v];
        visited[v] = 1;
        for (int i = 0; i < vertexNum; i++)
            if (edge[v][i] == 1 && visited[i] == 0)
                DFTraverse(i); //找到一个点就跳下去
    }
    
    1. 广搜
    template <typename DataType>
    void MGraphy<DataType>::BFTraverse(int v)
    {
        int Q[MaxSize];
        int front = -1, rear = -1;
        cout << vertex[v];
        visited[v] = 1;
        Q[++rear] = v;
        while (front != rear)
        {
            int w = Q[++front];                 //将队头元素出队,并送到w中
            for (int i = 0; i < vertexNum; i++) //对二维数组而言,就是扫描完一行再走
            {
                if (edge[w][i] == 1 && visited[i] == 0)
                {
                    cout << vertex[i];
                    visited[i] = 1;
                    Q[++rear] = i;
                }
            }
        }
    }
    
    1. Main函数做测试
    int main(void)
    {
        string Name[4] = {"a", "b", "c", "d"};
        MGraphy<string> *gra = new MGraphy<string>(Name, 4, 4);
        gra->DFTraverse(0);
        for (int i = 0; i < MaxSize; i++) //初始化访问标志数组
            visited[i] = 0;
        printf("
    ");
        gra->BFTraverse(0);
        return 0;
    }
    /*
    输入:
    0 3
    0 1
    1 3
    1 2
    输出
    abcd
    abdc
    */
    

    四、总结

    1. 这个是我看 王红梅数据结构做的笔记
    2. 这是第一次用代码,基于邻接表,实现图的存储与遍历。不算很难,但是奇妙的也很好
  • 相关阅读:
    Spark调优之JVM调优
    hive连接MySQL报错
    Kafka安装
    Linux系统Mini版配置相关
    Linux系统完整安装在虚拟机Mini
    hive_异常_01_(未解决)FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. org.apache.hadoop.hbase.HTableDescriptor.addFamily(Lorg/apache/hadoop/hbase/HColumnDescriptor;)V
    HBase的详细安装部署
    MyCat实现数据库与数据库之间的读写分离
    git+github
    react--入门
  • 原文地址:https://www.cnblogs.com/coderon/p/14792683.html
Copyright © 2011-2022 走看看