创建图的三种方法(邻接矩阵+邻接表+十字链表)

一、邻接矩阵
采用矩阵的方式来描述图中的连接各非连接关系,若不能连上用无穷大或者0来表示,但是如果边很稀少,顶点很多,那么将会有很大的浪费。同时,这个矩阵可以同时刻画有向图和无向图,无向图就是把有向图根据对角线对称即可。

这里写图片描述

1、思想:建立一个结构体,它包含了这个图所应该具备的顶点、边的条数、矩阵(二维数组的信息),同时因为边有三个信息,权值,连接两个顶点v1,v2,所以也用一个结构体表示

这里写图片描述
2、用到的函数:

MGraph CreateGraph_matric(int nvNum);
void InsertEdge_matric(MGraph Graph,Edge E);
MGraph biuldGraph_matric()

3、过程
(1)从文件中读入nv
(2)创建一个具有nv个顶点的图:

CreateGraph_matric(nv)

申请一个邻接矩阵图的空间,先把边设置成0,再用两个for循环遍历所有可能的边,每条边设置成无穷大(初始化)
(3)从文件中读入边的信息,读入边的连接信息(权值+两个被边连接的顶点),把他们的信息赋给Edge的边的结构体,再把这条边插进图中

InsertEdge_matric(Graph,E);

在插入函数中,说明:哪两个顶点间的权值是多少,即可

Graph->G[E->v1][E->v2]=E->weight;

二、邻接表
1、结构体

/*邻接点的定义*/
typedef int weightType;
typedef char dataType;
struct AdjvNode{
    Vertex Adjv;//邻接点的下标
    weightType weight;
    struct AdjvNode *next;
};
typedef struct AdjvNode *PtrToAdjvNode;


/*顶点表头结点的定义*/
struct Vnode{
    PtrToAdjvNode firstEdge;//边表头指针
    dataType data;
};
//开辟顶点结点的数组
typedef struct Vnode AdjList[MaxVertexNum];


/*邻接表-图的定义*/
struct GNode_AL{
    int nv;
    int ne;
    AdjList G;//顶点表
};
typedef struct GNode_AL *LGraph;

这里写图片描述

邻接表的结构是这样构建的:
整个图应该由顶点表+边表构成,怎么把他们连接起来?
(大框架)(里边包含顶点表,边数,顶点数)->(顶点表)(又包含 顶点内容+指向边表的指针)->(指针引出边表)(边表包含 :被指向边的顶点+权值+指向该条链表的下一个指针)

这里写图片描述
2、用到函数
同邻接矩阵(3个)
3、建立过程
同邻接矩阵。
初始化的时候有些区别。刚开始的时候,除了申请一个图的空间,还给每个顶点表也申请了空间,其实根本不用,因为我们创建的顶点表是用数组来创建的,已经申请了空间。把每个顶点表的头指针赋值为NULL。

扫描二维码关注公众号,回复: 1636290 查看本文章
//建立邻接表的图
LGraph biuldGraph_adjacencyList(){
    LGraph Graph;
    Edge E;
    int nv,i;

    FILE*fp;
     if((fp=fopen("E://数据结构//图 实验//matric1.txt","r"))==NULL)
    {
        printf("fail to open!");
        exit(0);
    }
    fscanf(fp,"%d\n",&nv);//顶点个数
    Graph=CreateGraph_adjacencyList(nv);//初始化有nv个顶点但没有边的图

    fscanf(fp,"%d\n",&Graph->ne);//读入边数
    if(Graph->ne!=0){
        E=(Edge)malloc(sizeof(struct ENode));
        for(i=0;i<Graph->ne;i++){
            fscanf(fp,"%d %d %d\n",&E->v1,&E->v2,&E->weight);//读入边的信息
            InsertEdge_adjacencyList(Graph,E);//把这条边插入矩阵信息中
        }
    }
    //读入顶点的数据
    for(i=0;i<Graph->nv;i++){
        fscanf(fp,"%c",&Graph->G[i].data);//读入A、B、C顶点的数据
    }
    return Graph;
}
//初始化有nv个顶点但没有边的图
LGraph CreateGraph_adjacencyList(int nvNum){
    Vertex v;
    LGraph Graph;
    //为这个图申请空间
    Graph =(LGraph)malloc(sizeof(struct GNode));
    Graph->nv=nvNum;
    Graph->ne=0;
    for(v=0;v<Graph->nv;v++)
        Graph->G[v].firstEdge=NULL;
    return Graph;
}

插入的时候,每一行的插入都是往前插

//把这条边插入邻接表信息中
void InsertEdge_adjacencyList(LGraph Graph,Edge E){
    PtrToAdjvNode newnode;//定义一个表头结点
    //建立一个v2邻接点
    newnode=(PtrToAdjvNode)malloc(sizeof(struct AdjvNode));
    newnode->Adjv=E->v2;//被连接到的点
    newnode->weight=E->weight;
    //将v2插入v1表头
    newnode->next=Graph->G[E->v1].firstEdge;
    Graph->G[E->v1].firstEdge=newnode;
}

如何理解将v2插入v1表头
这里写图片描述

三、十字链表
1、结构体

/*十字链表的结构体*/
//结点结构
struct ArcNode{
    int tailvex,headvex;//弧的头和顶点的位置
    struct ArcNode *hlink,*tlink;//头尾指针
    weightType weight;
};
typedef struct ArcNode *Arcbox;

//头结点
struct XNode{
    dataType data;
    Arcbox firstIn,firstOut;
};
typedef struct XNode xlist[MaxVertexNum];

/*十字链表-图的定义*/
struct OLGNode{
    int nv;
    int ne;
    xlist G;//邻接表
};
typedef struct OLGNode *OLGraph;

结点表和边表都多了一个方向的指针

这里写图片描述

2、过程
这个一模一样,不写了

OLGraph biuldGraph_arc(){}

下面这个for语句是要对两个头尾指针都要赋初值NULL,但是没有用括号,导致另一个指针瞎指,找了好久才发现,一定要细心!!

//初始化有nv个顶点但没有边的图
OLGraph CreateGraph_arc(int nvNum){
    Vertex v;
    OLGraph Graph;
    //为这个图申请空间
    Graph =(OLGraph)malloc(sizeof(struct OLGNode));
    Graph->nv=nvNum;
    Graph->ne=0;
    /*
    for(v=0;v<Graph->nv;v++)
        Graph->G[v].firstIn=NULL;
        Graph->G[v].firstOut=NULL;出错原因!!

    */
    for(v=0;v<Graph->nv;v++){
        Graph->G[v].firstIn=NULL;
        Graph->G[v].firstOut=NULL;
    }
    return Graph;
}
//把这条边插入邻接表信息中
void InsertEdge_arc(OLGraph Graph,Edge E){
    Arcbox A;
    A=(Arcbox)malloc(sizeof(struct ArcNode));//为结点申请空间

    A->weight=E->weight;
    A->headvex=E->v2;
    A->tailvex=E->v1;

    A->tlink=Graph->G[A->tailvex].firstOut;//出去的指针解决了
    Graph->G[A->tailvex].firstOut=A;//把出去的边连接上
    //解决firstIn,hlink的指针
    A->hlink=Graph->G[A->headvex].firstIn;
    Graph->G[A->headvex].firstIn=A;
}

firstout-tlink firstin-hlink

猜你喜欢

转载自blog.csdn.net/leafdown_/article/details/78743729