数据结构之图(存储结构、遍历)

一、图的存储结构

1.1 邻接矩阵

    图的邻接矩阵存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中的边或弧的信息。

    设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为:

    

    看一个实例,下图左就是一个无向图。

    

    从上面可以看出,无向图的边数组是一个对称矩阵。所谓对称矩阵就是n阶矩阵的元满足aij = aji。即从矩阵的左上角到右下角的主对角线为轴,右上角的元和左下角相对应的元全都是相等的。

    从这个矩阵中,很容易知道图中的信息。

    (1)要判断任意两顶点是否有边无边就很容易了;

    (2)要知道某个顶点的度,其实就是这个顶点vi在邻接矩阵中第i行或(第i列)的元素之和;

    (3)求顶点vi的所有邻接点就是将矩阵中第i行元素扫描一遍,arc[i][j]为1就是邻接点;

    而有向图讲究入度和出度,顶点vi的入度为1,正好是第i列各数之和。顶点vi的出度为2,即第i行的各数之和。

    若图G是网图,有n个顶点,则邻接矩阵是一个n*n的方阵,定义为:

    

    这里的wij表示(vi,vj)上的权值。无穷大表示一个计算机允许的、大于所有边上权值的值,也就是一个不可能的极限值。下面左图就是一个有向网图,右图就是它的邻接矩阵。

    

    那么邻接矩阵是如何实现图的创建的呢?代码如下。


#include <iostream>

#define MAXVERTEX   10
#define INFINITY    255
#define DEBUG

#ifdef DEBUG
#define Debug_Code( code_fragment ) { code_fragment }
#else
#define Debug_Code( code_fragment )
#endif // DEBUG


typedef char VertexType;        //Define the type of the vertex
typedef int MatrixValue;        //Define the value int the edge Matrix



typedef struct tagGraph
{
    VertexType vexs[MAXVERTEX];             //the array to store the vertexs.
    MatrixValue arc[MAXVERTEX][MAXVERTEX];  //We use the two dim array to store the edge matrix.
    int numVertexes;
    int numEdges;
}Graph;

int locate(Graph * g, VertexType ch)
{
    for(int i = 0; i < g->numVertexes; ++i)
    {
        if(g->vexs[i] == ch)
            return i;
    }
    return -1;
}

bool CreateGraph(Graph * g)
{
    std::cout << "Please input the number of Vertexes and the edges:" << std::endl;
    std::cin >> g->numVertexes >> g->numEdges;

    Debug_Code( std::cout << "The number of Vertex is " << g->numVertexes << std::endl
               << "The number of edges is " << g->numEdges << std::endl;
               );

    std::cout << "Please input the name of the vertexes standard as char type." << std::endl;

    for(int i = 0; i < g->numVertexes; i++)
    {
        g->vexs[i] = getchar();
        while(g->vexs[i] == '\n')
        {
            g->vexs[i] = getchar();
        }
    }

    Debug_Code (
                std::cout << "The vertex is: ";
                for(int i = 0; i < g->numVertexes; i++)
                    std::cout << g->vexs[i] << " ";
                std::cout << std::endl;
                );

    //Initialize the edge matrix
    for(int i = 0; i < g->numEdges; i++)
        for(int j = 0; j < g->numEdges; j++)
            g->arc[i][j] = INFINITY;

    //input the value for the edge matrix;
    for(int i = 0; i < g->numEdges; i++)
    {
        VertexType p, q;
        std::cout << "Please input the No." << i + 1
            << " edge  (vi,vj), and the value of the edge" << std::endl;
        p = getchar();
        while(p == '\n')
        {
            p = getchar();
        }
        q = getchar();
        while(q == '\n')
        {
            q = getchar();
        }
        int value = 0;
        std::cin >> value;

        int m = -1, n = -1;
        m = locate(g, p);
        n = locate(g, q);
        if(n == -1 || m == -1)
        {
            std::cout << " there is no this vertex." << std::endl;
            return false;

        }
        g->arc[m][n] = value;
        g->arc[n][m] = g->arc[m][n];
    }
    return true;
}

void printGraph(const Graph* g)
{

    std::cout << "The structure of the graph is\n\t";
    for(int i = 0; i < g->numVertexes; i++)
        std::cout << g->vexs[i]<<"\t";
    std::cout << std::endl;

    for(int i = 0; i < g->numVertexes; i++)
    {
        std::cout << g->vexs[i] << "\t";
        for(int j = 0; j < g->numVertexes; j++)
        {
            std::cout << g->arc[i][j] << "\t";

        }
        std::cout << std::endl;
    }
}

int main()
{
    //Test Case
    Graph g;
    CreateGraph(&g);
    printGraph(&g);

    return 0;
}

运行结果如下


 从代码中可以得到,n个顶点和e条边的无向网图的创建,时间复杂度为O(n + n2 + e),其中对邻接矩阵Grc的初始化耗费了O(n2)的时间。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值