图的邻接矩阵和邻接表存储及实现

前言

因为工作的需要深刻认识到了数据结构的重要性,故现在重新学习了数据结构相关知识,谨以此文来总结一下图的存储知识

声明:因个人能力有限,本文仅是个人的学习记录笔记,有错误之处还望指出

图的存储类型

  • 邻接矩阵(无向图/有向图)
    利用数组的方式来存储,适合稠密图的存储,表示方式唯一,但是时间复杂度较高,无向图的邻接矩阵是对称的,可以利用上三角/下三角来压缩存储
  • 邻接表(无向图/有向图)
    是顺序存储和链式存储相结合的一种存储方式,使用于稀疏图,表删方式不唯一,时间复杂度低
  • 邻接多重表(无向图)
  • 十字链表(有向图)

代码实现

邻接矩阵和邻接表

#include <stdio.h>
#include <stdlib.h>
#include "Graph.h"

/*数据存储封装*/

//最大顶点数目
#define  MAX_VERTEX_NUM  100

typedef char VertexType ;

//邻接矩阵存储
typedef struct  
{
    int vernum,arcnum;  //顶点数,弧长
    VertexType vertex[MAX_VERTEX_NUM];                 //顶点信息
    int  edge[MAX_VERTEX_NUM][MAX_VERTEX_NUM];          //边信息
}MGraph;


//邻接表存储
/*边表结点*/
typedef struct node{
    int adjvex;             //邻接点域
    struct node *next;      //指向下一邻接点的指针域
}EdgeNode;
/*顶点表节点*/
typedef struct vexnode{
    VertexType data;        //存储的数据
    EdgeNode *firstedge;    //指向的第一条边结点
}VHeadNode;
/*图*/
typedef struct 
{   
    int vernum,arcnum;  //顶点数,弧长
    VHeadNode adjlist[MAX_VERTEX_NUM];
}AdjList;



//邻接矩阵创建图
void CreateMGraph(MGraph *G){
    int i,j,k;
    char ch1,ch2;
    printf("请输入顶点数:");
    scanf("%d",&G->vernum);
    printf("请输入边数:");
    scanf("%d",&G->arcnum);
    printf("输入各个顶点信息(每个顶点以回车结束):\n");
    for(i=0;i<G->vernum;i++){
        getchar();  //清空缓冲区
        printf("输入第%d顶点:",i+1);
        scanf("%c",&(G->vertex[i]));
    }
    //将矩阵数据置为0
    for ( i = 0; i < G->vernum; i++)
        for ( j = 0; j < G->vernum; j++)
            G->edge[i][j]=0;

    //建立边信息
    for(k=0;k<G->arcnum;k++){
        getchar();
        printf("输入边信息(输入格式:顶点1,顶点2):\n");
        scanf("%c,%c",&ch1,&ch2);
        for ( i = 0; i < G->vernum; i++)
        for ( j = 0; j < G->vernum; j++){
           if(ch1==G->vertex[i]&&ch2==G->vertex[j]){        //比较顶点数组里的数据和用户输入的数据,一致则矩阵置为1
                G->edge[i][j]=1;    //有向矩阵
                // G->edge[i][j]=1; //无向矩阵
           }
        }
    }
}

//显示邻接矩阵
void DisplayMGraph(MGraph G){
    int i,j;
    printf("\n图的邻接矩阵为:\n");
    for(i=0;i<G.vernum;i++){
        for(j=0;j<G.vernum;j++)
            printf("%5d",G.edge[i][j]);
        printf("\n");
    }
}

//邻接表创建图(flag=0 无向图,flag=1 有向图)
void CreateAdjGraph(AdjList *g,int flag){
    int i,j,k;
    EdgeNode *p;
    if(flag==0)
        printf("将建立一个无向图");
    else    
        printf("建立一个有向图");
    printf("请输入顶点数:");
    scanf("%d",&g->vernum);
    printf("请输入边数:");
    scanf("%d",&g->arcnum);
    printf("输入各个顶点信息(每个顶点以回车结束):\n");
    for(i=0;i<g->vernum;i++){
        getchar();  //清空缓冲区
        printf("输入第%d顶点:\n",i+1);
        scanf("%c",&(g->adjlist[i].data));
        g->adjlist[i].firstedge=NULL;   //点的边表头指针为空
    }
    printf("\b请输入边的信息,输入格式为:序号1,序号2\n");
    for(k=0;k<g->arcnum;k++){
        printf("请输入第%d条边\n",k);
        //将编号为i的结点加入到邻接表中
        scanf("%d,%d",&i,&j);
        p=(EdgeNode *)malloc(sizeof(EdgeNode));
        p->adjvex=j;        //邻接点序号为j
        p->next=g->adjlist[i].firstedge;       //将新节点p插到顶点vi边表头
        g->adjlist[i].firstedge=p;

        //将编号为j的结点添加到邻接表中,有向图不需要添加
        if(flag==0){
            p=(EdgeNode *)malloc(sizeof(EdgeNode));
            p->adjvex=i;        //邻接点序号为j
            p->next=g->adjlist[j].firstedge;       //将新节点p插到顶点vi边表头
            g->adjlist[j].firstedge=p;
        }
    }
}
//显示邻接表
void DisplayAdjGraph(AdjList g){
    int i;
    EdgeNode *p;
    printf("\n图的邻接表表示:\n");
    for(i=0;i<g.vernum;i++){
        printf("%2d[%c]",i,g.adjlist[i].data);
        p=g.adjlist[i].firstedge;
        while(p!=NULL){
            printf("-->[%d]",p->adjvex);
            p=p->next;
        }
        printf("\n");
    }
}
//菜单项
void menu(){
    printf("=================\n");
    printf("1.邻接矩阵存储图\n");
    printf("2.邻接表存储图\n");
    printf("=================\n");

}

int main(){
    MGraph G;
    AdjList g;
    int choose,flag;
    menu();
while(1){
    scanf("%d",&choose);
    switch (choose)
    {
    case 1: 
        printf("邻接矩阵存储\n");
        CreateMGraph(&G);
        DisplayMGraph(G);
        break;
    case 2:
        printf("邻接表存储\n"); 
        printf("选择图的类型(1.有向图,0.无向图)\n");
        scanf("%d",&flag);
        CreateAdjGraph(&g,flag);
        DisplayAdjGraph(g);
        break;
    default:
        printf("输入错误\n"); 
        break;
    }
	}  
}

结果图

邻接表

在这里插入图片描述
邻接矩阵
在这里插入图片描述

而塞过 2021-5-16

关于我:一个就要进入互联网,经历社会毒打的99小伙

下一站(javascript)
下一站(html)

  • 10
    点赞
  • 93
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值