图的存储形式——邻接矩阵(数组)

邻接矩阵:用两个数组分别存储数据元素(顶点)的信息和数据元素之间的关系(边或弧)的信息。

比如考虑下面这个有向图:

如果用邻接矩阵存储可以表示为:

1.顶点数组:

2.邻接矩阵:

图的遍历:

深度优先(DFS):

深度优先搜索遍历类似于树的先根遍历,是树的先根遍历的推广。假设初始状态是图中所有顶点未曾访问过,则深度优先搜索可从图中的某个顶点v出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到;若此时图中还有顶点未访问,则另选图中未访问的顶点作为起始点,重复上述过程,直至所有顶点被访问。

上图深度优先遍历结果:abcdfeghi

广度优先(BFS):

广度优先搜索类似于树的层次遍历。假设从图中某顶点v出发,在访问了v之后,依次访问v的各个未曾访问的邻接点,然后分别从这些邻接点触发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问,直至图中所有已被访问的顶点的邻接点都被访问到。若此时仍有顶点没访问,另选图中未访问的顶点作为起始点,重复上述过程,直至所有顶点被访问。

上图广度优先遍历结果:abgcehidf

具体实现:

/************************************
图的邻接矩阵(数组)表示
by Rowandjj
2014/6/22
************************************/

#include<iostream>
using namespace std;

#define INFINTY_INT_MAX  0x7fffffff    //代表正无穷
#define MAX_VERTIEX_NUM 20    //最大顶点个数
#define MAX_INFO 20

typedef enum{DG,DN,AG,AN}GraphKind;//有向图、有向网、无向图、无向网

typedef struct
{
    int adj;//顶点关系类型
    char *info;//该弧的相关信息
}ArcCell,AdjMatrix[MAX_VERTIEX_NUM][MAX_VERTIEX_NUM];

typedef struct
{
    char vexs[MAX_VERTIEX_NUM];//顶点向量
    AdjMatrix arcs;//邻接矩阵
    int vexnum,arcnum;//顶点数、弧数
    GraphKind kind;//种类
}MGraph,*pMGraph;

bool visited[MAX_VERTIEX_NUM];//访问标志数组(全局)
bool (*VisitFunc)(char);

bool Visit(char v)
{
    cout<<v;
    return true;
}
//----------------操作-------------------------------
int LocateVex(MGraph G,char u);//若G中存在顶点u,则返回该顶点在图中位置;否则返回-1
bool CreateDG(pMGraph G);//创建有向图
bool CreateDN(pMGraph G);//创建有向网
bool CreateAG(pMGraph G);//创建无向图
bool CreateAN(pMGraph G);//创建无向网

bool CreateGraph(pMGraph G);//构造图
void DestroyGraph(pMGraph G);//销毁图G
char GetVex(MGraph G,int v);//初始条件: 图G存在,v是G中某个顶点的序号。操作结果: 返回v的值
bool PutVex(pMGraph G,char v,char iValue);//初始条件: 图G存在,v是G中某个顶点。操作结果: 对v赋新值value
int FirstAdjVex(MGraph G,char v);//返回v的第一个邻接顶点的序号
int NextAdjVex(MGraph G,char v,char w);//返回v的(相对于w的)下一个邻接顶点的序号,否则返回-1
void InsertVex(pMGraph G,char v);//在图G中增添新顶点v(不增添与顶点相关的弧,留待InsertArc()去做)
bool DeleteVex(pMGraph G,char v);//删除G中顶点v及其相关的弧
bool InsertArc(pMGraph G,char v,char w);//在G中增添弧<v,w>,若G是无向的,则还增添对称弧<w,v>
bool DeleteArc(pMGraph G,char v,char w);//在G中删除弧<v,w>,若G是无向的,则还删除对称弧<w,v>

void DFSTravel(MGraph G,bool (*Visit)(char));//深度优先
void DFS(MGraph G,int v);
void BFSTravel(MGraph G,bool (*Visit)(char));//广度优先
void Display(MGraph G);

//----------------辅助队列--------------------------

typedef struct _QUEUENODE_
{
    int data;
    struct _QUEUENODE_ *next;
}QueueNode,*pQueueNode;

typedef struct _QUEUE_
{
    int size;
    pQueueNode pHead;
    pQueueNode pTail;
}Queue,*pQueue;

bool InitQueue(pQueue Q);
bool DestroyQueue(pQueue Q);
bool DeQueue(pQueue Q,int* e);
bool EnQueue(pQueue Q, int e);
bool QueueEmpty(Queue Q);
//------------------------------------------
bool InitQueue(pQueue Q)
{
    Q->pHead = Q->pTail = (pQueueNode)malloc(sizeof(QueueNode));
    if(!Q->pHead)
    {
        return false;
    }
    Q->pHead->next = NULL;
    Q->size = 0;
    return true;
}

bool DestroyQueue(pQueue Q)
{
    pQueueNode pTemp = Q->pHead->next;
    while(pTemp != NULL)
    {
        Q->pHead->next = pTemp->next;
        free(pTemp);
        pTemp = Q->pHead->next;
    }
    free(Q->pHead);
    Q->size = 0;
    return true;
}
bool QueueEmpty(Queue Q)
{
    return Q.size == 0;
}

bool DeQueue(pQueue Q,int* e)
{
    pQueueNode pDel = Q->pHead->next;
    if(pDel != NULL)
    {
        *e = pDel->data;
        Q->pHead->next = pDel->next;
        if(Q->pTail == pDel)
        {
            Q->pTail = Q->pHead;
        }
        free(pDel);
        Q->size--;
    }
    return true;
}
bool EnQueue(pQueue Q, int e)
{
    pQueueNode pNew = (pQueueNode)malloc(sizeof(QueueNode));
    if(!pNew)
    {
        return false;
    }
    pNew->next = NULL;
    pNew->data = e;

    Q->pTail->next = pNew;
    Q->pTail = pNew;
    Q->size++;

    return true;
}
//------------------------------------------
int LocateVex(MGraph G,char u)
{
    int i = 0;
    for(i = 0; i < G.vexnum;i++)
    {
        if(u == G.vexs[i])
        {
            return i;
        }
    }
    return -1;
}

bool CreateDG(pMGraph G)
{
    int incInfo = 0;
    int i,j,k,l;
    char va,vb;
    char *info;
    char s[MAX_INFO] = {0};//存放弧信息
    cout<<"请输入有向图G的顶点数,弧数,弧是否含其它信息(是:1,否:0)"<<endl;
    cin>>G->vexnum;
    cin>>G->arcnum;
    cin>>incInfo;
    cout<<"请输入顶点值"<<endl;

    for(i = 0; i < G->vexnum; i++)//构造顶点向量
    {
        cin>>G->vexs[i];
    }

    for(i = 0; i < G->vexnum; i++)//初始化邻接矩阵
    {
        for(j = 0 ;j < G->vexnum; j++)
        {
            G->arcs[i][j].adj = 0;
            G->arcs[i][j].info = NULL;
        }
    }

    cout<<"请输入每条弧的弧头和弧尾"<<endl;

    for(k = 0; k < G->arcnum; k++)
    {
        cin>>va;
        cin>>vb;

        i = LocateVex(*G,va);
        j = LocateVex(*G,vb);

        G->arcs[i][j].adj = 1;
        if(incInfo)
        {
            cout<<"输入该弧的信息"<<endl;
            cin>>s;
            l = strlen(s);
            if(l)
            {
                info = (char *)malloc(sizeof(char) * (l+1));
                strcpy(info,s);
                G->arcs[i][j].info = info;
            }
        }
    }
    G->kind = DG;
    return true;
}

bool CreateDN(pMGraph G)
{
    int incInfo;
    int i,j,k,l,w;
    char s[MAX_INFO];
    cout<<"请输入有向网G的顶点数,弧数,弧是否含其它信息(是:1,否:0)"<<endl;
    cin>>G->vexnum;
    cin>>G->arcnum;
    cin>>incInfo;
    char va,vb;//分别代表弧头、弧尾
    char *pInfo;

    cout<<"请输入顶点值"<<endl;
    for(i = 0; i < G->vexnum; i++)
    {
        cin>>G->vexs[i];
    }
    for(i = 0; i < G->vexnum; i++)
    {
        for(j = 0; j < G->vexnum; j++)
        {
            G->arcs[i][j].adj = INFINTY_INT_MAX;//网
            G->arcs[i][j].info = NULL;
        }
    }

    cout<<"请输入弧的头、尾、权值"<<endl;
    for(k = 0; k < G->arcnum; k++)
    {
        cout<<"弧头"<<endl;
        cin>>va;
        cout<<"弧尾"<<endl;
        cin>>vb;
        cout<<"权值"<<endl;
        cin>>w;
        i = LocateVex(*G,va);
        j = LocateVex(*G,vb);

        G->arcs[i][j].adj = w;
        if(incInfo)
        {
            cout<<"请输入该弧的信息"<<endl;
            cin>>s;
            l = strlen(s);
            if(l)
            {
                pInfo = (char *)malloc(sizeof(char)*(l+1));
                strcpy(pInfo,s);
                G->arcs[i][j].info = pInfo;
            }
        }

    }

    G->kind = DN;
    return true;
}

bool CreateAG(pMGraph G)//创建无向图
{
    int incInfo;
    int i,j,k,l;
    char va,vb;
    cout<<"请输入无向图G的顶点数,边数,边是否含其它信息(是:1,否:0):"<<endl;

    cin>>G->vexnum;
    cin>>G->arcnum;
    cin>>incInfo;
    char s[MAX_INFO];
    char *info;
    //初始化顶点
    for(i = 0; i < G->vexnum; i++)
    {
        cin>>G->vexs[i];
    }
    //初始化邻接矩阵
    for(i = 0; i < G->vexnum; i++)
    {
        for(j = 0; j < G->vexnum; j++)
        {
            G->arcs[i][j].adj = 0;//图
            G->arcs[i][j].info = NULL;
        }
    }
    cout<<"请输入每条边的两个顶点"<<endl;
    for(k = 0; k < G->arcnum; k++)
    {
        cin>>va;
        cin>>vb;

        i = LocateVex(*G,va);
        j = LocateVex(*G,vb);

        G->arcs[i][j].adj = G->arcs[j][i].adj = 1;
        if(incInfo)
        {
            cin>>s;
            l = strlen(s);
            if(l)
            {
                info = (char *)malloc(sizeof(char)*(l+1));
                strcpy(info,s);
                G->arcs[i][j].info = G->arcs[j][i].info = info;
            }
        }
    }
    G->kind = AG;
    return true;
}
bool CreateAN(pMGraph G)
{
    int incInfo;
    int i,j,k;
    char va,vb;
    int w;
    char s[MAX_INFO];
    char *info;

    cout<<"请输入无向网G的顶点数,边数,边是否含其它信息(是:1,否:0):";
    cin>>G->vexnum;
    cin>>G->arcnum;
    cin>>incInfo;

    for(i = 0; i < G->vexnum; i++)
    {
        cin>>G->vexs[i];
    }
    for(i = 0; i < G->vexnum; i++)
    {
        for(j = 0; j < G->vexnum; j++)
        {
            G->arcs[i][j].adj = INFINTY_INT_MAX;
            G->arcs[i][j].info = NULL;
        }
    }
    cout<<"请输入每条边的两个顶点以及权值"<<endl;
    for(k = 0; k < G->vexnum; k++)
    {
        cin>>va;
        cin>>vb;
        cin>>w;

        i = LocateVex(*G,va);
        j = LocateVex(*G,vb);
        G->arcs[i][j].adj = G->arcs[j][i].adj = w;

        if(incInfo)
        {
            cout<<"请输入该边的相关信息"<<endl;
            cin>>s;
            w = strlen(s);
            if(w)
            {
                info = (char *)malloc(sizeof(char)*(w+1));
                strcpy(info,s);
                G->arcs[i][j].info = G->arcs[j][i].info = info;
            }
        }
    }

    G->kind = AN;
    return true;
}
bool CreateGraph(pMGraph G)
{
    cout<<"请输入图G的类型(有向图:0,有向网:1,无向图:2,无向网:3):";
    scanf("%d",&(*G).kind);
    switch((*G).kind)
    {
    case DG: return CreateDG(G); /* 构造有向图 */
    case DN: return CreateDN(G); /* 构造有向网 */
    case AG: return CreateAG(G); /* 构造无向图 */
    case AN: return CreateAN(G); /* 构造无向网 */
    default: return false;
   }
}
void DestroyGraph(pMGraph G)
{
    int i,j;
    if(G->kind < 2)//有向tu
    {
        for(i = 0; i < G->vexnum; i++)
        {
            for(j = 0; j < G->vexnum; j++)
            {
                if(G->kind == 0 && G->arcs[i][j].adj == 1 || G->kind == 1 && G->arcs[i][j].adj != INFINTY_INT_MAX)
                {
                    free(G->arcs[i][j].info);
                    G->arcs[i][j].info = NULL;
                }
            }
        }
    }else
    {
        for(i = 0; i < G->vexnum; i++)
        {
            for(j = i+1; j < G->vexnum; j++)
            {
                if(G->kind == 2 && G->arcs[i][j].adj == 1 || G->kind == 3 && G->arcs[i][j].adj != INFINTY_INT_MAX)
                {
                    free(G->arcs[i][j].info);
                    G->arcs[i][j].info = G->arcs[j][i].info =NULL;
                }
            }
        }
    }
}
char GetVex(MGraph G,int v)
{
    if(v > G.vexnum || v < 0)
    {
        exit(0);
    }
    return G.vexs[v];
}
bool PutVex(pMGraph G,char v,char iValue)
{
    int k = 0;
    k = LocateVex(*G,v);
    if( k < 0)
    {
        return false;
    }
    G->vexs[k] = iValue;
    return true;
}
int FirstAdjVex(MGraph G,char v)
{
    int i,j = 0,k;
    k = LocateVex(G,v);
    if(G.kind == AN || G.kind == DN)
    {
        j = INFINTY_INT_MAX;
    }
    for(i = 0; i < G.vexnum; i++)
    {
        if(G.arcs[k][i].adj != j)
        {
            return i;
        }
    }
    return -1;
}
int NextAdjVex(MGraph G,char v,char w)//返回v的(相对于w的)下一个邻接顶点的序号,若w是v的最后一个邻接顶点,则返回-1
{
    int k1,k2;
    int i,j = 0;
    k1 = LocateVex(G,v);
    k2 = LocateVex(G,w);

    if(G.kind == AN || G.kind == DN)
    {
        j = INFINTY_INT_MAX;
    }

    for(i = k2+1; i < G.vexnum ; i++)
    {
        if(G.arcs[k1][i].adj != j)
        {
            return i;
        }
    }
    return -1;
}

void Display(MGraph G)
{
    int i,j;
    cout<<"顶点:";
    for(i = 0; i < G.vexnum; i++)
    {
        cout<<G.vexs[i]<<" ";
    }
    cout<<endl;
    cout<<"边"<<endl;
    for(i = 0; i < G.vexnum; i++)
    {
        for(j = 0; j < G.vexnum; j++)
        {
            cout<<G.arcs[i][j].adj<<" ";
        }
        cout<<endl;
    }
}
void InsertVex(pMGraph G,char v)
{
    int index = G->vexnum;
    G->vexnum+=1;
    G->vexs[index] = v;
    for(int i = 0; i <= index; i++)
    {
        if(G->kind % 2)//网
        {
            G->arcs[i][index].adj = G->arcs[index][i].adj = INFINTY_INT_MAX;
        }else
        {
            G->arcs[i][index].adj = G->arcs[index][i].adj = 0;
        }
        G->arcs[index][i].info = NULL;
        G->arcs[i][index].info = NULL;
    }

}
bool DeleteVex(pMGraph G,char v)
{
    int k,m = 0;
    int i,j;
    //1.找到顶点v的序号
    k = LocateVex(*G,v);
    if(k < 0)
    {
        return false;
    }
    if(G->kind == DN || G->kind == AN)//网
    {
        m = INFINTY_INT_MAX;
    }
    //2.更改弧数(分有向图和无向图)
    for(i = 0; i < G->vexnum; i++)
    {
        if(G->arcs[i][k].adj != m)
        {
            if(G->arcs[i][k].info)//释放相关信息
            {
                free(G->arcs[i][k].info);
            }
            G->arcnum--;
        }
    }
    if(G->kind == DG || G->kind == AG)//有向图
    {
        for(i = 0; i < G->vexnum; i++)
        {
            if(G->arcs[k][i].adj != m)
            {
                if(G->arcs[k][i].info)//释放相关信息
                {
                    free(G->arcs[k][i].info);
                }
                G->arcnum--;
            }
        }
    }
    //3.更改顶点数组内容及大小
    for(i = k+1; i < G->vexnum; i++)
    {
        G->vexs[i-1] = G->vexs[i];
    }
    //4.更改邻接矩阵
    for(i = 0; i < G->vexnum; i++)
    {
        for(j = k+1;j < G->vexnum; j++)
        {
            G->arcs[i][j-1] = G->arcs[i][j];
        }
    }
    for(i = 0; i < G->vexnum; i++)
    {
        for(j = k+1;j < G->vexnum; j++)
        {
            G->arcs[j-1][i] = G->arcs[j][i];
        }
    }

    G->vexnum--;
    return true;
}
bool InsertArc(pMGraph G,char v,char w)
{
    int i,j,k,l;
    char s[MAX_INFO];
    char *pinfo;
    //1.找到v、w的序号
    i = LocateVex(*G,v);
    j = LocateVex(*G,w);
    if(i < 0 || j < 0)
    {
        return false;
    }
    //2.如果是网,需输入权值.是图则更改邻接矩阵相应值
    if(G->kind == DN || G->kind == AN)
    {
        cout<<"输入权值:";
        cin>>G->arcs[i][j].adj;
    }else
    {
        G->arcs[i][j].adj = 1;
    }
    //3.如果有相关信息,输入之
    cout<<"该弧是否有相关信息(0:否 1:是):"<<endl;
    cin>>k;
    if(k)
    {
        cout<<"输入相关信息:";
        cin>>s;
        l = strlen(s);
        if(l)
        {
            pinfo = (char *)malloc(sizeof(char)*(l+1));
            strcpy(pinfo,s);
            G->arcs[i][j].info = pinfo;
        }
    }
    //4.如果是无向的,添加对称弧
    if(G->kind == AG || G->kind == AN)
    {
        G->arcs[j][i].adj = G->arcs[i][j].adj;
        G->arcs[j][i].info = G->arcs[i][j].info;
    }
    G->arcnum++;
    return true;
}
bool DeleteArc(pMGraph G,char v,char w)
{
    int i,j;
    //1.找到v、w的位置
    i = LocateVex(*G,v);
    j = LocateVex(*G,w);
    if(i < 0 || j < 0)
    {
        return false;
    }
    //2.如果是图则将邻接矩阵对应位置的值改为0,否则改为INT_MAX
    if(G->kind == DG || G->kind == AG)
    {
        G->arcs[i][j].adj = 0;
    }else
    {
        G->arcs[i][j].adj = INFINTY_INT_MAX;
    }    

    if(G->arcs[i][j].info)
    {
        free(G->arcs[i][j].info);
        G->arcs[i][j].info = NULL;
    }
    //3.如果是无向的,需删除对称弧
    if(G->kind == AG || G->kind == AN)
    {
        G->arcs[j][i].adj = G->arcs[i][j].adj;
        G->arcs[j][i].info = NULL;
    }
    G->arcnum--;
    return true;
}
void DFSTravel(MGraph G,bool (*Visit)(char))
{
    int v;
    VisitFunc = Visit;
    for(v = 0; v < G.vexnum; v++)
    {
        visited[v] = false;
    }
    for(v = 0; v < G.vexnum; v++)
    {
        if(!visited[v])
        {
            DFS(G,v);
        }
    }
    cout<<endl;
}
void DFS(MGraph G,int v)
{
    char w1,v1;
    int w;

    visited[v] = true;
    VisitFunc(G.vexs[v]);
    v1 = GetVex(G,v);

    for(w = FirstAdjVex(G,v1);w>=0;w = NextAdjVex(G,v1,w1=GetVex(G,w)))
    {
        if(!visited[w])
        {
            DFS(G,w);
        }
    }
}
void BFSTravel(MGraph G,bool (*Visit)(char))
{
    Queue q;
    InitQueue(&q);
    char w1,u1;
    int i,u,w;
    for(i = 0; i < G.vexnum; i++)
    {
        visited[i] = false;
    }

    for(i = 0; i < G.vexnum; i++)
    {
        if(!visited[i])
        {
            visited[i] = true;
            Visit(G.vexs[i]);
            EnQueue(&q,i);

            while(!QueueEmpty(q))
            {
                DeQueue(&q,&u);
                u1 = GetVex(G,u);
                for(w = FirstAdjVex(G,u1);w>=0;w = NextAdjVex(G,u1,w1=GetVex(G,w)))
                {
                    if(!visited[w])
                    {
                        visited[w] = true;
                        Visit(G.vexs[w]);
                        EnQueue(&q,w);
                    }

                }
            }
        }
    }
    DestroyQueue(&q);
    cout<<endl;
}
int main()
{
    MGraph G;
    CreateDG(&G);
    Display(G);
    cout<<"深度优先遍历"<<endl;
    DFSTravel(G,Visit);
    cout<<"广度优先遍历"<<endl;
    BFSTravel(G,Visit);
    return 0;
}

测试:

图的存储形式——邻接矩阵(数组),布布扣,bubuko.com

时间: 2024-08-11 09:57:30

图的存储形式——邻接矩阵(数组)的相关文章

图的存储形式——邻接表

邻接表:邻接表是图的一种链式存储结构.在邻接表中,对图中每个顶点建立一个单链表,第i个单链表中的节点表示依附于顶点vi的边(对有向图是以顶点vi为尾的弧).每个结点有三个域组成,其中邻接点域指示与顶点vi邻接的点在途中的位置,链域指示下一条边或者弧的结点:数据域存储和边或者弧相关的信息,如权值等.每个链表上附设一个表头结点.在表头结点中,除了设置链域指向链表第一个结点之外,还设置有存储顶点vi的名.如下所示: 实现: /**************************************

java 数据结构 图中使用的一些常用算法 图的存储结构 邻接矩阵:图的邻接矩阵存储方式是用两个数组来标示图。一个一位数组存储图顶点的信息,一个二维数组(称为邻接矩阵)存储图中边或者弧的信息。 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 实例如下,左图是一个无向图。右图是邻接矩阵表示:

以下内容主要来自大话数据结构之中,部分内容参考互联网中其他前辈的博客. 图的定义 图是由顶点的有穷非空集合和顶点之间边的集合组成,通过表示为G(V,E),其中,G标示一个图,V是图G中顶点的集合,E是图G中边的集合. 无边图:若顶点Vi到Vj之间的边没有方向,则称这条边为无项边(Edge),用序偶对(Vi,Vj)标示. 对于下图无向图G1来说,G1=(V1, {E1}),其中顶点集合V1={A,B,C,D}:边集合E1={(A,B),(B,C),(C,D),(D,A),(A,C)}: 有向图:若

图的存储之邻接矩阵

1.图 (1).图是一种非线性结构:主要由顶点和边构成: (2).<> 代表有向图,( )代表无向图 (3).无向图有N个顶点时,最多有N*(N-1)/2条边:有向图最多有N*(N-1)条边; (4).权:边上具有相关的数,带权图叫做网络; (5).邻接顶点: 与其接触边上的顶点: (6).度:与顶点V关联的边数:有向图中度 = 出度 + 入度: (7).简单路径:路径上各顶点互不重复, (8).回路/环:路径上第一个顶点与最后一个顶点重合: (9).连通图/强连通图:各顶点之间有边联系,有向

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

转载请注明出处:勿在浮沙筑高台http://blog.csdn.net/luoshixian099/article/details/51888031 图的存储方法有邻接表.邻近矩阵.邻接多重表.十字链表等.本篇文章介绍两种简单且比较常用的两种方法:邻接表与邻接矩阵方法. 以下面的无向图为例,介绍两种存储方法.有向图的存储方法类似,只是边是单方向,无向图的边可以看做双向. 1.邻接链表法 邻接链表表示法对图中的每个顶点建立一个带头的边链表:第i条链表代表依附于顶点vi所有边信息,若为有向图,则表示

图(网)的存储结构(数组存储表示即邻接矩阵、邻接表)

图(Graph)是一种非线性结构 图的特点(多对多),顶点之间的关系是任意的,图中任意两个顶点之间都可能相关,顶点的前驱和后继个数无限制. 图:数据元素间存在多对多关系的数据结构,加上一组基本操作构成的抽象数据类型. 图的基本术语 顶点:图中的数据元素. 弧:若 <v, w>∈VR,则 <v, w> 表示从 v 到 w 的一条弧,且称 v 为弧尾,称 w 为弧头,此时的图称为有向图. G1 = (V1, A1)          V1 = {v1, v2, v3, v4} A1 =

图的存储结构:邻接矩阵(邻接表)&amp;链式前向星

[概念]疏松图&稠密图: 疏松图指,点连接的边不多的图,反之(点连接的边多)则为稠密图. Tips:邻接矩阵与邻接表相比,疏松图多用邻接表,稠密图多用邻接矩阵. 邻接矩阵: 开一个二维数组graph[ ][ ]来记录图中点a与点b之间是否连通,初始化为0(或者-1之类的看情况):如果图中有可忽略的重边(如 只需重边中的最小边或最大边),则保存需要的那条边的边权,但如果有无法忽略的重边,就一定不要用邻接矩阵. int graph[MAXN][MAXN]; void graphInit() { me

图的存储-邻接矩阵

分不清自己这是预习,还是复习了 BFS和DFS总算要开始了 先复习一下图 所谓邻接矩阵(Adjacency Matrix)的存储结构,就是用一维数组存储图中顶点的信息,用矩阵表示图中各顶点之间的邻接关系.假设图G=(V,E)有n 个确定的顶点,即V={v0,v1,-,vn-1},则表示G 中各顶点相邻关系为一个n×n 的矩阵,矩阵的元素为: 其中,wij 表示边(vi,vj)或<vi,vj>上的权值:∞表示一个计算机允许的.大于所有边上权值的数. 用邻接矩阵表示法表示图如图8.7 所示. 用邻

图的存储结构(邻接矩阵)

图的存储结构(邻接矩阵) 让编程改变世界 Change the world by program 图的存储结构 图的存储结构相比较线性表与树来说就复杂很多. 我们回顾下,对于线性表来说,是一对一的关系,所以用数组或者链表均可简单存放.树结构是一对多的关系,所以我们要将数组和链表的特性结合在一起才能更好的存放. 那么我们的图,是多对多的情况,另外图上的任何一个顶点都可以被看作是第一个顶点,任一顶点的邻接点之间也不存在次序关系. 我们仔细观察以下几张图,然后深刻领悟一下: 因为任意两个顶点之间都可能

图的存储:链式前向星(边集数组)

申明:本文中提及的所有存图结构都用静态数组实现,而非链表. 0.什么是链式前向星 链式前向星是一种存图的结构,例如前向星.邻接矩阵.边表.邻接表等也是存图的结构. 1.链式前向星有何优点 链式前向星:空间利用率高,在各类竞赛中常被使用. 邻接矩阵:需要开N*N的空间,在各类竞赛中常被卡. 邻接表:空间复杂度略小于邻接矩阵,但会被极端数据卡爆,且无法记录权值. 边表:无法迅速判断两点连通性,以至不适用于大多数图的算法. 前向星:具有排序操作,时间复杂度高. 2.同类结构介绍 邻接矩阵:开二维数组,