算法导论--图的存储(邻接表与邻接矩阵)

版权声明:转载请注明出处! PS:欢迎大家提出疑问或指正文章的错误! https://blog.csdn.net/luoshixian099/article/details/51888031

转载请注明出处:勿在浮沙筑高台http://blog.csdn.net/luoshixian099/article/details/51888031


图的存储方法有邻接表、邻近矩阵、邻接多重表、十字链表等。本篇文章介绍两种简单且比较常用的两种方法:邻接表与邻接矩阵方法。
以下面的无向图为例,介绍两种存储方法。有向图的存储方法类似,只是边是单方向,无向图的边可以看做双向。
这里写图片描述

1.邻接链表法

邻接链表表示法对图中的每个顶点建立一个带头的边链表;第i条链表代表依附于顶点 vi 所有边信息,若为有向图,则表示以顶点 vi 为弧尾的边信息。邻接链接可以分为两部分,表头结点定义了顶点信息,随后的边链表表达了关于此顶点边信息。
这里写图片描述
所有表头结点以顺序结构的形式存储,以便可以随机访问任一顶点的边链表。上图的邻接链表表示法如下:
这里写图片描述
存储空间
对于有n个顶点,e条边的无向图而言,需要n个表头结点和2e个边链表结点。
度、出度和入度
无向图顶点度的概念是依附于该结点的边的个数。从边链表表示法中可以很容易的计算顶点的度,即对应边链表结点的个数。
有向图顶点的出度是以该顶点为弧尾的弧的个数。同理,入度是以该顶点为弧头的弧的个数。在邻接链表表示法中,有向图顶点的出度为对应边链表结点的数目。有向图顶点的入度计算比较复杂,必须要遍历整个邻接链表才能得出结果。一种解决方法是再建立一个逆邻接表法,或者采用十字链表法。


代码

/************************************************************************
CSDN 勿在浮沙筑高台 http://blog.csdn.net/luoshixian099算法导论--图的存储(邻接链表)2016年7月12日                   
************************************************************************/
#include <iostream>
using namespace std;
typedef struct VertexNode  //链表表头结点
{
    char data;
    struct ArcNode * firstarc;//指向第一条边
}VertexNode;
typedef struct ArcNode  //边链表结点
{
    char data;
    struct ArcNode * nextarc;//指向下一条边
}ArcNode;
ArcNode * InSertArcNode(char name) //新建边结点,待插入到边链表中
{
    ArcNode * p = new ArcNode;
    p->data = name;
    p->nextarc = NULL;
    return p;
}
VertexNode * AdjList()//邻接链表表示法
{
    ArcNode * p=NULL;
    VertexNode * List_head = new VertexNode[9]; //顺序存储表头结点
    int count = 0;
    List_head[count].data = 'A';
    p = List_head[count].firstarc = InSertArcNode('B');
    p = p->nextarc = InSertArcNode('D');
    p = p->nextarc = InSertArcNode('E');
    count++;
    List_head[count].data = 'B';
    p = List_head[count].firstarc = InSertArcNode('A');
    p = p->nextarc = InSertArcNode('C');
    p = p->nextarc = InSertArcNode('E');
    count++;
    List_head[count].data = 'C';
    p = List_head[count].firstarc = InSertArcNode('B');
    p = p->nextarc = InSertArcNode('F');
    count++;
    List_head[count].data = 'D';
    p = List_head[count].firstarc = InSertArcNode('A');
    p = p->nextarc = InSertArcNode('G');
    count++;
    List_head[count].data = 'E';
    p = List_head[count].firstarc = InSertArcNode('A');
    p = p->nextarc = InSertArcNode('B');
    p = p->nextarc = InSertArcNode('G');
    count++;
    List_head[count].data = 'F';
    p = List_head[count].firstarc = InSertArcNode('C');
    count++;
    List_head[count].data = 'G';
    p = List_head[count].firstarc = InSertArcNode('D');
    p = p->nextarc = InSertArcNode('E');
    p = p->nextarc = InSertArcNode('H');
    count++;
    List_head[count].data = 'H';
    p = List_head[count].firstarc = InSertArcNode('G');
    p = p->nextarc = InSertArcNode('I');
    count++;
    List_head[count].data = 'I';
    p = List_head[count].firstarc = InSertArcNode('H');

    return List_head;
}

int main()
{   
    char vextex[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I' };
    VertexNode * GRAPH = AdjList();  //创建图--邻接链表
    ArcNode *p = NULL;
    for (int i = 0; i < 9;i++)  //输出
    {
        cout << GRAPH[i].data << ": ";
        p = GRAPH[i].firstarc;
        while (p != NULL)
        {
            cout << p->data << ",";
            p = p->nextarc;
        }
        cout << endl;
    }
    return 0;
}

2.邻接矩阵法

对于包含n个顶点的图,建立一个n×n的矩阵arc;用arc[i][j]的取值表示弧 <vi,vj> 的信息。
矩阵中第i行表示图的顶点 vi 与其他顶点的弧信息;
对于无权图而言,若弧存在则对应元素为1,否则为0;有权图而言,弧存在即为弧的权重,否则为无穷大;
这里写图片描述
最开始的无向无权图的邻接矩阵表示法如下:
这里写图片描述
存储空间
对于无向图而言,邻接矩阵为一个对称矩阵,我们只需要存储矩阵下三角即可,因此对于包含n个顶点的图,只需要 n(n1)2 个存储空间。而对于有向图,则需要 n2 个存储空间。
度、出度与入度
针对无权图:
无向图顶点的度,即为第i行的所有元素和。
有向图顶点的出度,即为第i行的所有元素和;入度为第i列的所有元素和。


代码:


/************************************************************************
CSDN 勿在浮沙筑高台 http://blog.csdn.net/luoshixian099算法导论--图的存储(邻接矩阵)2016年7月12日                   
************************************************************************/
#include <iostream>
using namespace std;
void AdjMatrix(char arc[][9])
{
    for (int i = 0; i < 9; i++)   //初始化邻接矩阵
        for (int j = 0; j < 9; j++)
        {
            arc[i][j] = 0;
        }
    arc[0][1] = arc[0][3] = arc[0][4] = 1;
    arc[1][0] = arc[1][2] = arc[1][4] = 1;
    arc[2][1] = arc[2][5] = 1;
    arc[3][0] = arc[3][6] = 1;
    arc[4][0] = arc[4][1] = arc[4][6] = 1;
    arc[5][2] = 1;
    arc[6][3] = arc[6][4] = arc[6][7] = 1;
    arc[7][6] = arc[7][8] = 1;
    arc[8][7] = 1;
}
int main()
{   
    char vextex[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I' };
    char arc[9][9] = { 0 };
    AdjMatrix(arc);
    for (int i = 0; i < 9; i++)
    {
        cout << vextex[i] << ": ";
        for (int j = 0; j < 9; j++)
        {
            if (arc[i][j]==1)
            {
                cout << vextex[j] << ",";
            }
        }
        cout << endl;
    }
    return 0;
}

Reference:
数据结构-耿国华

猜你喜欢

转载自blog.csdn.net/luoshixian099/article/details/51888031
今日推荐