图的结构

一、图的存储结构

我们知道,数据之间的关系可分为3种,分别是“一对一”、“一对多”、“多对多”,前两种关系可分别用数组和树存储,而多对多的数据结构则需要用图来存储。

图是用(V,E)来表示的,其中V是顶点的集合,E是边的集合。对于图的存储,主要有邻接矩阵邻接表两种结构。

二、邻接矩阵

**邻接矩阵是一个存储着边信息的矩阵,顶点用矩阵下标表示。**对于矩阵M,如果M(i,j)=1,则顶点i和顶点j之间存在一条边;若M(i,j)=0,则顶点i与顶点j之间没有边;

对于无向图来说,若M(i,j)=1,则M(j,i)=1.也就是邻接矩阵是一个对称矩阵。而对于有向图来说,则不一定是一个对称矩阵。

**此结构适用于稠密图。**因为对于顶点数很多边很少的稀疏图,用这种结构会浪费空间,即矩阵中为1的元素很少,却占用了很大的空间。下面用代码一步步实现图的邻接矩阵存储。

**邻接矩阵由顶点数、边数、定点集合、边集合组成。**定点集合为一维数组,边集合为二维数组。为节省空间,我们根据顶点的数量动态分配数组的大小。

typedef struct juzhen
{   
 int num1;//顶点数   
  int num2;//边数
 dingdianleixing *a;//顶点集合       bianleixing **b;//边集合
}juzhen;

下面是矩阵的具体构造

void creatjuzhen(juzhen *g)
{
 int i,j,k;   
  printf("请输入顶点数和边数:");  
    scanf("%d %d",&g->num1,&g->num2); 
//动态生成顶点数组的大小 
 g->a=(dingdianleixing *)malloc(g->num1*sizeof(dingdianleixing));  
  //动态生成边二维数组的大小  
       g->b=(bianleixing**)malloc(g->num1*sizeof(bianleixing));    for(i=0;i<g->num1;i++)
      {     
        g->b[i]=(bianleixing*)malloc(g->num1*sizeof(bianleixing));  
      }
   //初始化矩阵所有元素为0   
    for(i=0;i<g->num1;i++)        
    for(j=0;j<g->num1;j++)   
     {       
      g->b[i][j]=0;  
        }  
          //输入边的信息  
            for(k=0;k<g->num2;k++) 
               {     
                 scanf("%d %d",&i,&j);   
                     g->b[i][j]=1;  
                          g->b[j][i]=1;  
          }  
          //输出矩阵  
         for(i=0;i<g->num1;i++)   
          {       
           for(j=0;j<g->num1;j++)  
             {        
             printf("%d\t",g->b[i][j]);    
           } 
                printf("\n"); 
          }
 }   
                   

邻接矩阵结构的完整代码

#include<stdio.h>
#include <malloc.h>
typedef char dingdianleixing;
typedef int bianleixing;
typedef struct juzhen
{    
int num1;//顶点数   
 int num2;//边数   
  dingdianleixing *a;//顶点集合   
   bianleixing **b;//边集合
}juzhen;
void creatjuzhen(juzhen *g)
{    
int i,j,k;    
printf("请输入顶点数和边数:");    
scanf("%d %d",&g->num1,&g->num2);   
 //动态生成顶点数组的大小     
 g->a=(dingdianleixing *)malloc(g->num1*sizeof(dingdianleixing));    //动态生成边二维数组的大小     
 g->b=(bianleixing**)malloc(g->num1*sizeof(bianleixing));    for(i=0;i<g->num1;i++)    
 {       
  g->b[i]=(bianleixing*)malloc(g->num1*sizeof(bianleixing));   
   }
   //初始化矩阵所有元素为0    
   for(i=0;i<g->num1;i++)       
    for(j=0;j<g->num1;j++)   
     {        
     g->b[i][j]=0;   
      }   
       //输入边的信息    
       for(k=0;k<g->num2;k++)   
        {      
         scanf("%d %d",&i,&j);      
          g->b[i][j]=1;     
            g->b[j][i]=1;   
             }   
              //输出矩阵     
              for(i=0;i<g->num1;i++)  
                {        
                for(j=0;j<g->num1;j++)    
                {        
                printf("%d\t",g->b[i][j]);   
                 }   
                  printf("\n");    
                  }
                  }
                  int main()
                  {  
                  juzhen *g; 
                   g=(juzhen*)malloc(sizeof(juzhen)); 
                    creatjuzhen(g);
                  }

三、图的邻接表存储

对于边数相对于顶点较少的图,邻接矩阵会浪费空间,为此,我们可以考虑用链表来动态分配空间。

对于来说邻接表,顶点用一维数组来存储,称为顶点节点。每个数组元素除了存储顶点数据以外,还会存储指向第一个邻接点的指针f。与每个顶点节点相连接的顶点称为边节点,边节点的结构体包括顶点对应的下标和指向下一个边节点的指针。

//边节点的结构体 
typedef struct s1
{    
int p1;   
 struct s1*next;
 }s1;
 //顶点节点 
 typedef struct s2{    
 dingdianleixing v;   
  s1*f;//指向第一条边
 }s2;

对于整体的邻接表,只要包括顶点数、边数以及顶点集合。

typedef struct linjiebiao
{    int num1;//顶点数量     
int num2;//边数量    
  s2*v;//顶点集合
}linjiebiao;

下面是邻接表的具体创建

void linjiebiao_creat(linjiebiao *g)
{    int i,j,k;    
scanf("%d %d",&g->num1,&g->num2);   
 g->v=(s2*)malloc(g->num1*sizeof(s2));    //初始化顶点所指的第一条边    for(i=0;i<g->num1;i++)   
  {       
   g->v[i].f=NULL;  
     }    
     //输入图的信息  
       s1* s8;    
       for(k=0;k<g->num2;k++)   
        {      
     scanf("%d %d",&i,&j);       //始终将插入的节点放在顶点所指的第一条边       
         //将顶点j连在顶点i之后      
          s8=(s1*)malloc(sizeof(s1));      
           s8->p1=j;      
            s8->next=g->v[i].f;       
             g->v[i].f=s8;        //将顶点i连在顶点j之后         s8=(s1*)malloc(sizeof(s1));      
              s8->p1=i;      
               s8->next=g->v[j].f;       
                g->v[j].f=s8;
    }
    //输出邻接表    
    s1 *len=NULL;    
    for(i=0;i<g->num1;i++)   
     {       
      if(g->v[i].f!=NULL)       
       {            
       len=g->v[i].f;        
       }        
       while(len!=NULL)      
         {           
          printf("%d--%d\t",i,len->p1);           
           len=len->next;      
             }      
               printf("\n");  
                 }
                 }

完整代码

#include<stdio.h>
#include <malloc.h>
typedef char dingdianleixing;
typedef int bianleixing;
//边节点的结构体 
typedef struct s1{    
int p1;    
struct s1*next;}s1;
//顶点节点 
typedef struct s2{    
dingdianleixing v;    
s1*f;//指向第一条边
}s2;
typedef struct linjiebiao{    
int num1;//顶点数量     
int num2;//边数量     
 s2*v;//顶点集合
}linjiebiao;
void linjiebiao_creat(linjiebiao *g)
{   
 int i,j,k;    
scanf("%d %d",&g->num1,&g->num2);   
 g->v=(s2*)malloc(g->num1*sizeof(s2));    //初始化顶点所指的第一条边    for(i=0;i<g->num1;i++)  
   {       
    g->v[i].f=NULL;    
    }   
     //输入图的信息    
     s1* s8;    
     for(k=0;k<g->num2;k++) 
        {       
        scanf("%d %d",&i,&j);       //始终将插入的节点放在顶点所指的第一条边       
        //将顶点j连在顶点i之后      
         s8=(s1*)malloc(sizeof(s1));   
             s8->p1=j;    
                s8->next=g->v[i].f;  
                      g->v[i].f=s8;        //将顶点i连在顶点j之后            s8=(s1*)malloc(sizeof(s1));      
                       s8->p1=i;    
                          s8->next=g->v[j].f;     
                             g->v[j].f=s8;
   }
   //输出邻接表    
   s1 *len=NULL;    
   for(i=0;i<g->num1;i++)  
     {       
      if(g->v[i].f!=NULL)      
        {           
         len=g->v[i].f;       
          }       
           while(len!=NULL)       
            {           
             printf("%d--%d\t",i,len->p1);           
              len=len->next;      
                }       
                 printf("\n");   
                  }
                  }
                  int main()
                  {   
                   linjiebiao *g;   
                    g=(linjiebiao *)malloc((sizeof(linjiebiao)));    linjiebiao_creat(g);
  }
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值