SlideShare a Scribd company logo
1 of 6
Download to read offline
图的邻接表存储表示

                                及重要的基本操作

/* 图的邻接表存储表示及重要的基本操作 */

/* 图的邻接表存储表示,真的很重要,要不然后面全是白搭 */
                     ,
 #define MAX_VERTEX_NUM 20
 typedef enum{DG,DN,UDG,UDN}GraphKind; /* {有向图,有向网,无向图,无向网} */
                                              ,   ,   ,   }
 typedef struct ArcNode
 {
   int adjvex; /* 该弧所指向的顶点的位置 */
   struct ArcNode *nextarc; /* 指向下一条弧的指针 */
   InfoType *info; /* 网的权值指针) */
 }ArcNode; /* 表结点 */
 typedef struct
 {
   VertexType data; /* 顶点信息 */
   ArcNode *firstarc; /* 第一个表结点的地址,指向第一条依附该顶点的弧的指针 */
                                      ,
 }VNode,AdjList[MAX_VERTEX_NUM]; /* 头结点 */

typedef struct
 {
   AdjList vertices;
   int vexnum,arcnum; /* 图的当前顶点数和弧数 */
   GraphKind kind; /* 图的种类标志 */
 }ALGraph;

有向图、无向图的邻接表:(注意表结点的域)




网邻接表的表示:注意表结点的域中多加一个权值域
      1
//
//基本操作选择性的看吧
Status LocateVex(ALGraph G,VertexType u)
    { /* 初始条件:图 G 存在,u 和 G 中顶点有相同特征 */
       /* 操作结果:若 G 中存在顶点 u,则返回该顶点在图中位置;否则返回 NULL */
       int i;
       for(i=0;i<G.vexnum;++i)
          if(strcmp(u,G.vertices[i].data)==0)
              return i;
       return NULL;
    }


//数据结构题集(C 语言版)习题 7.14
Status CreateALGraph(ALGraph &G)
{//建立有向图的邻接表
scanf(&G.vexnum, &G.arcnum, &IncInfo);
  for(i=0; i<G.vexnum; i++)
     {scanf(&G.vertices[i].data); //构造表头向量(顶点信息)
     G.vertices[i].firstarc=NULL; }//初始化指针,头结点指针为空
    for(k=0; k<G.arcnum; k++)
     {scanf(&v1,&v2);
        i=LocateVex(G,v1); j=LocateVex(G,v2);//确定 v1,v2 在 G 中位置
        p=(ArcNode *)malloc(sizeof(ArcNode));//假定有足够的空间
        *p=(j, G.vertices[i].firstarc, NULL);//对结点赋值
        G.vertices[i].firstarc=p;//插入到表头结点后
        if(IncInfo) scanf(*p->Info);
    }
}

Status FirstAdjVex(ALGraph G,VertexType v)

          2
{ /* 初始条件:图 G 存在,v 是 G 中某个顶点 */
    /* 操作结果:返回 v 的第一个邻接顶点的序号。若顶点在 G 中没有邻接顶点,则返回
NULL*/
    LinkList p;
    int v1;
     v1=LocateVex(G,v); /* v1 为顶点 v 在图 G 中的序号 */
     p=G.vertices[v1].firstarc;
     if(p)
        return p->data.adjvex;
     else
        return NULL;
 }

Status equalvex(ElemType a,ElemType b)
 { /* DeleteArc()、DeleteVex()和 NextAdjVex()要调用的函数 */
    if(a.adjvex==b.adjvex)
       return OK;
    else
       return ERROR;
 }
 Status NextAdjVex(ALGraph G,VertexType v,VertexType w)
 { /* 初始条件:图 G 存在,v 是 G 中某个顶点,w 是 v 的邻接顶点 */
    /* 操作结果:返回 v 的(相对于 w 的)下一个邻接顶点的序号。若 w 是 v 的最后一个邻接
点,则返回 NULL */
/*用到的函数 Point()为查找表 L 中满足条件的结点。如找到,返回指向该结点的指针,         p
指向该结点的前驱(若该结点是 */
    /* 首元结点,则 p=NULL)。如表 L 中无满足条件的结点,则返回 NULL,p 无定义。*/
    LinkList p,p1; /* p1 在 Point()中用作辅助指针*/
    ElemType e;
    int v1;
  v1=LocateVex(G,v); /* v1 为顶点 v 在图 G 中的序号 */
  e.adjvex=LocateVex(G,w); /* e.adjvex 为顶点 w 在图 G 中的序号 */
  p=Point(G.vertices[v1].firstarc,e,equalvex,&p1); /* p 指向顶点 v 的链表中邻接顶点为 w 的结
点 */
  if(!p||!p->next) /* 没找到 w 或 w 是最后一个邻接点 */
      return -1;
  else /* p->data.adjvex==w */
      return p->next->data.adjvex; /* 返回 v 的(相对于 w 的)下一个邻接顶点的序号 */
 }
//注:下面的内容有点小复杂,应该考不到吧。有兴趣的可以看一下。

 void InsertVex(ALGraph *G,VertexType v)
 { /* 初始条件:图 G 存在,v 和图中顶点有相同特征 */
    /* 操作结果:在图 G 中增添新顶点 v(不增添与顶点相关的弧,留待 InsertArc()去做) */

       3
strcpy((*G).vertices[(*G).vexnum].data,v); /* 构造新顶点向量 */
     (*G).vertices[(*G).vexnum].firstarc=NULL;
     (*G).vexnum++; /* 图 G 的顶点数加 1 */
 }

 Status DeleteVex(ALGraph *G,VertexType v)
 { /* 初始条件: G 存在, 是 G 中某个顶点。
                   图 v      操作结果:删除 G 中顶点 v 及其相关的弧 */
    int i,j,k;
    ElemType e;
    LinkList p,p1;
     j=LocateVex(*G,v); /* j 是顶点 v 的序号 */
     if(j<0) /* v 不是图 G 的顶点 */
         return ERROR;
     i=ListLength((*G).vertices[j].firstarc); /* 以 v 为出度的弧或边数,在 bo2-8.c 中 */
     (*G).arcnum-=i; /* 边或弧数-i */
     if((*G).kind%2) /* 网 */
         while((*G).vertices[j].firstarc) /* 对应的弧或边链表不空 */
         {
             ListDelete(&(*G).vertices[j].firstarc,1,&e); /* 删除链表的第 1 个结点,并将值赋给 e */
             free(e.info); /* 释放动态生成的权值空间 */
         }
     else /* 图 */
        DestroyList(&(*G).vertices[i].firstarc); /* 销毁弧或边链表,在 bo2-8.c 中 */
     (*G).vexnum--; /* 顶点数减 1 */
     for(i=j;i<(*G).vexnum;i++) /* 顶点 v 后面的顶点前移 */
        (*G).vertices[i]=(*G).vertices[i+1];
     for(i=0;i<(*G).vexnum;i++) /* 删除以 v 为入度的弧或边且必要时修改表结点的顶点位置值
*/
     {
         e.adjvex=j;
         p=Point((*G).vertices[i].firstarc,e,equalvex,&p1); /* Point()在 func2-1.c 中 */
         if(p) /* 顶点 i 的邻接表上有 v 为入度的结点 */
         {
             if(p1) /* p1 指向 p 所指结点的前驱 */
                 p1->next=p->next; /* 从链表中删除 p 所指结点 */
             else /* p 指向首元结点 */
                 (*G).vertices[i].firstarc=p->next; /* 头指针指向下一结点 */
             if((*G).kind<2) /* 有向 */
             {
                 (*G).arcnum--; /* 边或弧数-1 */
                 if((*G).kind==1) /* 有向网 */
                     free(p->data.info); /* 释放动态生成的权值空间 */
             }
             free(p); /* 释放 v 为入度的结点 */

         4
}
        for(k=j+1;k<=(*G).vexnum;k++) /* 对于 adjvex 域>j 的结点,其序号-1 */
        {
           e.adjvex=k;
            p=Point((*G).vertices[i].firstarc,e,equalvex,&p1); /* Point()在 func2-1.c 中 */
            if(p)
              p->data.adjvex--; /* 序号-1(因为前移) */
        }
    }
    return OK;
}

Status InsertArc(ALGraph *G,VertexType v,VertexType w)
{ /* 初始条件:图 G 存在,v 和 w 是 G 中两个顶点 */
   /* 操作结果:在 G 中增添弧<v,w>,若 G 是无向的,则还增添对称弧<w,v> */
   ElemType e;
   int i,j;
    i=LocateVex(*G,v); /* 弧尾或边的序号 */
    j=LocateVex(*G,w); /* 弧头或边的序号 */
    if(i<0||j<0)
        return ERROR;
    (*G).arcnum++; /* 图 G 的弧或边的数目加 1 */
    e.adjvex=j;
    e.info=NULL; /* 初值 */
    if((*G).kind%2) /* 网 */
    {
        e.info=(int *)malloc(sizeof(int)); /* 动态生成存放权值的空间 */
        printf("请输入弧(边)%s→%s 的权值: ",v,w);
        scanf("%d",e.info);
    }
    ListInsert(&(*G).vertices[i].firstarc,1,e); /* 将 e 插在弧尾的表头,在 bo2-8.c 中 */
    if((*G).kind>=2) /* 无向,生成另一个表结点 */
    {
        e.adjvex=i; /* e.info 不变 */
        ListInsert(&(*G).vertices[j].firstarc,1,e); /* 将 e 插在弧头的表头 */
    }
    return OK;
}
Status DeleteArc(ALGraph *G,VertexType v,VertexType w)
{ /* 初始条件:图 G 存在,v 和 w 是 G 中两个顶点 */
   /* 操作结果:在 G 中删除弧<v,w>,若 G 是无向的,则还删除对称弧<w,v> */
   int i,j;
   Status k;
   ElemType e;

        5
i=LocateVex(*G,v); /* i 是顶点 v(弧尾)的序号 */
    j=LocateVex(*G,w); /* j 是顶点 w(弧头)的序号 */
    if(i<0||j<0||i==j)
        return ERROR;
    e.adjvex=j;
    k=DeleteElem(&(*G).vertices[i].firstarc,&e,equalvex); /* 在 func2-1.c 中 */
    if(k) /* 删除成功 */
    {
        (*G).arcnum--; /* 弧或边数减 1 */
        if((*G).kind%2) /* 网 */
            free(e.info);
        if((*G).kind>=2) /* 无向,删除对称弧<w,v> */
        {
            e.adjvex=i;
            DeleteElem(&(*G).vertices[j].firstarc,&e,equalvex);
        }
        return OK;
    }
    else /* 没找到待删除的弧 */
       return ERROR;
}




        6

More Related Content

What's hot

第6章 自底向上的lr分析法
第6章 自底向上的lr分析法第6章 自底向上的lr分析法
第6章 自底向上的lr分析法tjpucompiler
 
企业常用Sql
企业常用Sql企业常用Sql
企业常用Sqljade_side
 
MATLAB_曲面作图
MATLAB_曲面作图MATLAB_曲面作图
MATLAB_曲面作图byron zhao
 
第七章 图[3]
第七章 图[3]第七章 图[3]
第七章 图[3]Wang Yizhe
 
OOP in C - Virtual Function (Chinese Version)
OOP in C - Virtual Function (Chinese Version)OOP in C - Virtual Function (Chinese Version)
OOP in C - Virtual Function (Chinese Version)Kai-Feng Chou
 
1 C入門教學
1  C入門教學1  C入門教學
1 C入門教學Sita Liu
 

What's hot (10)

Delta (rostock)
Delta (rostock)Delta (rostock)
Delta (rostock)
 
第6章 自底向上的lr分析法
第6章 自底向上的lr分析法第6章 自底向上的lr分析法
第6章 自底向上的lr分析法
 
企业常用Sql
企业常用Sql企业常用Sql
企业常用Sql
 
第4章函数
第4章函数第4章函数
第4章函数
 
MATLAB_曲面作图
MATLAB_曲面作图MATLAB_曲面作图
MATLAB_曲面作图
 
第七章 图[3]
第七章 图[3]第七章 图[3]
第七章 图[3]
 
OOP in C - Virtual Function (Chinese Version)
OOP in C - Virtual Function (Chinese Version)OOP in C - Virtual Function (Chinese Version)
OOP in C - Virtual Function (Chinese Version)
 
Processing 03
Processing 03Processing 03
Processing 03
 
1 C入門教學
1  C入門教學1  C入門教學
1 C入門教學
 
Ppt 167-173
Ppt 167-173Ppt 167-173
Ppt 167-173
 

Viewers also liked

Big Data for the Rest of Us - OpenWest 2014 - Matt Asay
Big Data for the Rest of Us - OpenWest 2014 - Matt AsayBig Data for the Rest of Us - OpenWest 2014 - Matt Asay
Big Data for the Rest of Us - OpenWest 2014 - Matt AsayMatt Asay
 
DataStax: Steps to successfully implementing NoSQL in the enterprise
DataStax: Steps to successfully implementing NoSQL in the enterpriseDataStax: Steps to successfully implementing NoSQL in the enterprise
DataStax: Steps to successfully implementing NoSQL in the enterpriseDataStax Academy
 
Cassandra Summit 2014: TitanDB - Scaling Relationship Data and Analysis with ...
Cassandra Summit 2014: TitanDB - Scaling Relationship Data and Analysis with ...Cassandra Summit 2014: TitanDB - Scaling Relationship Data and Analysis with ...
Cassandra Summit 2014: TitanDB - Scaling Relationship Data and Analysis with ...DataStax Academy
 
Titan: Scaling Graphs and TinkerPop3
Titan: Scaling Graphs and TinkerPop3Titan: Scaling Graphs and TinkerPop3
Titan: Scaling Graphs and TinkerPop3Matthias Broecheler
 
A Graph Service for Global Web Entities Traversal and Reputation Evaluation B...
A Graph Service for Global Web Entities Traversal and Reputation Evaluation B...A Graph Service for Global Web Entities Traversal and Reputation Evaluation B...
A Graph Service for Global Web Entities Traversal and Reputation Evaluation B...HBaseCon
 
C* Summit 2013: Time for a New Relationship - Intuit's Journey from RDBMS to ...
C* Summit 2013: Time for a New Relationship - Intuit's Journey from RDBMS to ...C* Summit 2013: Time for a New Relationship - Intuit's Journey from RDBMS to ...
C* Summit 2013: Time for a New Relationship - Intuit's Journey from RDBMS to ...DataStax Academy
 
NYC* 2013 — "Using Cassandra for DVR Scheduling at Comcast"
NYC* 2013 — "Using Cassandra for DVR Scheduling at Comcast"NYC* 2013 — "Using Cassandra for DVR Scheduling at Comcast"
NYC* 2013 — "Using Cassandra for DVR Scheduling at Comcast"DataStax Academy
 
Cassandra & puppet, scaling data at $15 per month
Cassandra & puppet, scaling data at $15 per monthCassandra & puppet, scaling data at $15 per month
Cassandra & puppet, scaling data at $15 per monthdaveconnors
 
Cassandra at eBay - Cassandra Summit 2012
Cassandra at eBay - Cassandra Summit 2012Cassandra at eBay - Cassandra Summit 2012
Cassandra at eBay - Cassandra Summit 2012Jay Patel
 
Titan: Big Graph Data with Cassandra
Titan: Big Graph Data with CassandraTitan: Big Graph Data with Cassandra
Titan: Big Graph Data with CassandraMatthias Broecheler
 
Migrating Netflix from Datacenter Oracle to Global Cassandra
Migrating Netflix from Datacenter Oracle to Global CassandraMigrating Netflix from Datacenter Oracle to Global Cassandra
Migrating Netflix from Datacenter Oracle to Global CassandraAdrian Cockcroft
 
Titan: The Rise of Big Graph Data
Titan: The Rise of Big Graph DataTitan: The Rise of Big Graph Data
Titan: The Rise of Big Graph DataMarko Rodriguez
 

Viewers also liked (13)

Big Data for the Rest of Us - OpenWest 2014 - Matt Asay
Big Data for the Rest of Us - OpenWest 2014 - Matt AsayBig Data for the Rest of Us - OpenWest 2014 - Matt Asay
Big Data for the Rest of Us - OpenWest 2014 - Matt Asay
 
DataStax: Steps to successfully implementing NoSQL in the enterprise
DataStax: Steps to successfully implementing NoSQL in the enterpriseDataStax: Steps to successfully implementing NoSQL in the enterprise
DataStax: Steps to successfully implementing NoSQL in the enterprise
 
Advanced Operations
Advanced OperationsAdvanced Operations
Advanced Operations
 
Cassandra Summit 2014: TitanDB - Scaling Relationship Data and Analysis with ...
Cassandra Summit 2014: TitanDB - Scaling Relationship Data and Analysis with ...Cassandra Summit 2014: TitanDB - Scaling Relationship Data and Analysis with ...
Cassandra Summit 2014: TitanDB - Scaling Relationship Data and Analysis with ...
 
Titan: Scaling Graphs and TinkerPop3
Titan: Scaling Graphs and TinkerPop3Titan: Scaling Graphs and TinkerPop3
Titan: Scaling Graphs and TinkerPop3
 
A Graph Service for Global Web Entities Traversal and Reputation Evaluation B...
A Graph Service for Global Web Entities Traversal and Reputation Evaluation B...A Graph Service for Global Web Entities Traversal and Reputation Evaluation B...
A Graph Service for Global Web Entities Traversal and Reputation Evaluation B...
 
C* Summit 2013: Time for a New Relationship - Intuit's Journey from RDBMS to ...
C* Summit 2013: Time for a New Relationship - Intuit's Journey from RDBMS to ...C* Summit 2013: Time for a New Relationship - Intuit's Journey from RDBMS to ...
C* Summit 2013: Time for a New Relationship - Intuit's Journey from RDBMS to ...
 
NYC* 2013 — "Using Cassandra for DVR Scheduling at Comcast"
NYC* 2013 — "Using Cassandra for DVR Scheduling at Comcast"NYC* 2013 — "Using Cassandra for DVR Scheduling at Comcast"
NYC* 2013 — "Using Cassandra for DVR Scheduling at Comcast"
 
Cassandra & puppet, scaling data at $15 per month
Cassandra & puppet, scaling data at $15 per monthCassandra & puppet, scaling data at $15 per month
Cassandra & puppet, scaling data at $15 per month
 
Cassandra at eBay - Cassandra Summit 2012
Cassandra at eBay - Cassandra Summit 2012Cassandra at eBay - Cassandra Summit 2012
Cassandra at eBay - Cassandra Summit 2012
 
Titan: Big Graph Data with Cassandra
Titan: Big Graph Data with CassandraTitan: Big Graph Data with Cassandra
Titan: Big Graph Data with Cassandra
 
Migrating Netflix from Datacenter Oracle to Global Cassandra
Migrating Netflix from Datacenter Oracle to Global CassandraMigrating Netflix from Datacenter Oracle to Global Cassandra
Migrating Netflix from Datacenter Oracle to Global Cassandra
 
Titan: The Rise of Big Graph Data
Titan: The Rise of Big Graph DataTitan: The Rise of Big Graph Data
Titan: The Rise of Big Graph Data
 

More from mengyingchina

哈佛幸福课[升级版]
哈佛幸福课[升级版]哈佛幸福课[升级版]
哈佛幸福课[升级版]mengyingchina
 
数据结构复习笔记 图的遍历及连通性问题
数据结构复习笔记 图的遍历及连通性问题数据结构复习笔记 图的遍历及连通性问题
数据结构复习笔记 图的遍历及连通性问题mengyingchina
 
数据结构复习笔记 拓扑排序Topological+sort
数据结构复习笔记 拓扑排序Topological+sort数据结构复习笔记 拓扑排序Topological+sort
数据结构复习笔记 拓扑排序Topological+sortmengyingchina
 
数据结构复习笔记 字符串模式匹配算(Kmp)
数据结构复习笔记 字符串模式匹配算(Kmp)数据结构复习笔记 字符串模式匹配算(Kmp)
数据结构复习笔记 字符串模式匹配算(Kmp)mengyingchina
 
数据结构复习笔记 关键路径+Critical+paths
数据结构复习笔记 关键路径+Critical+paths数据结构复习笔记 关键路径+Critical+paths
数据结构复习笔记 关键路径+Critical+pathsmengyingchina
 

More from mengyingchina (7)

哈佛幸福课[升级版]
哈佛幸福课[升级版]哈佛幸福课[升级版]
哈佛幸福课[升级版]
 
幸福课
幸福课幸福课
幸福课
 
数据结构复习笔记 图的遍历及连通性问题
数据结构复习笔记 图的遍历及连通性问题数据结构复习笔记 图的遍历及连通性问题
数据结构复习笔记 图的遍历及连通性问题
 
数据结构复习笔记 拓扑排序Topological+sort
数据结构复习笔记 拓扑排序Topological+sort数据结构复习笔记 拓扑排序Topological+sort
数据结构复习笔记 拓扑排序Topological+sort
 
数据结构复习笔记 字符串模式匹配算(Kmp)
数据结构复习笔记 字符串模式匹配算(Kmp)数据结构复习笔记 字符串模式匹配算(Kmp)
数据结构复习笔记 字符串模式匹配算(Kmp)
 
数据结构复习笔记 关键路径+Critical+paths
数据结构复习笔记 关键路径+Critical+paths数据结构复习笔记 关键路径+Critical+paths
数据结构复习笔记 关键路径+Critical+paths
 
文献综述
文献综述文献综述
文献综述
 

数据结构复习笔记 图的邻接表存储表示及重要的基本操作

  • 1. 图的邻接表存储表示 及重要的基本操作 /* 图的邻接表存储表示及重要的基本操作 */ /* 图的邻接表存储表示,真的很重要,要不然后面全是白搭 */ , #define MAX_VERTEX_NUM 20 typedef enum{DG,DN,UDG,UDN}GraphKind; /* {有向图,有向网,无向图,无向网} */ , , , } typedef struct ArcNode { int adjvex; /* 该弧所指向的顶点的位置 */ struct ArcNode *nextarc; /* 指向下一条弧的指针 */ InfoType *info; /* 网的权值指针) */ }ArcNode; /* 表结点 */ typedef struct { VertexType data; /* 顶点信息 */ ArcNode *firstarc; /* 第一个表结点的地址,指向第一条依附该顶点的弧的指针 */ , }VNode,AdjList[MAX_VERTEX_NUM]; /* 头结点 */ typedef struct { AdjList vertices; int vexnum,arcnum; /* 图的当前顶点数和弧数 */ GraphKind kind; /* 图的种类标志 */ }ALGraph; 有向图、无向图的邻接表:(注意表结点的域) 网邻接表的表示:注意表结点的域中多加一个权值域 1
  • 2. // //基本操作选择性的看吧 Status LocateVex(ALGraph G,VertexType u) { /* 初始条件:图 G 存在,u 和 G 中顶点有相同特征 */ /* 操作结果:若 G 中存在顶点 u,则返回该顶点在图中位置;否则返回 NULL */ int i; for(i=0;i<G.vexnum;++i) if(strcmp(u,G.vertices[i].data)==0) return i; return NULL; } //数据结构题集(C 语言版)习题 7.14 Status CreateALGraph(ALGraph &G) {//建立有向图的邻接表 scanf(&G.vexnum, &G.arcnum, &IncInfo); for(i=0; i<G.vexnum; i++) {scanf(&G.vertices[i].data); //构造表头向量(顶点信息) G.vertices[i].firstarc=NULL; }//初始化指针,头结点指针为空 for(k=0; k<G.arcnum; k++) {scanf(&v1,&v2); i=LocateVex(G,v1); j=LocateVex(G,v2);//确定 v1,v2 在 G 中位置 p=(ArcNode *)malloc(sizeof(ArcNode));//假定有足够的空间 *p=(j, G.vertices[i].firstarc, NULL);//对结点赋值 G.vertices[i].firstarc=p;//插入到表头结点后 if(IncInfo) scanf(*p->Info); } } Status FirstAdjVex(ALGraph G,VertexType v) 2
  • 3. { /* 初始条件:图 G 存在,v 是 G 中某个顶点 */ /* 操作结果:返回 v 的第一个邻接顶点的序号。若顶点在 G 中没有邻接顶点,则返回 NULL*/ LinkList p; int v1; v1=LocateVex(G,v); /* v1 为顶点 v 在图 G 中的序号 */ p=G.vertices[v1].firstarc; if(p) return p->data.adjvex; else return NULL; } Status equalvex(ElemType a,ElemType b) { /* DeleteArc()、DeleteVex()和 NextAdjVex()要调用的函数 */ if(a.adjvex==b.adjvex) return OK; else return ERROR; } Status NextAdjVex(ALGraph G,VertexType v,VertexType w) { /* 初始条件:图 G 存在,v 是 G 中某个顶点,w 是 v 的邻接顶点 */ /* 操作结果:返回 v 的(相对于 w 的)下一个邻接顶点的序号。若 w 是 v 的最后一个邻接 点,则返回 NULL */ /*用到的函数 Point()为查找表 L 中满足条件的结点。如找到,返回指向该结点的指针, p 指向该结点的前驱(若该结点是 */ /* 首元结点,则 p=NULL)。如表 L 中无满足条件的结点,则返回 NULL,p 无定义。*/ LinkList p,p1; /* p1 在 Point()中用作辅助指针*/ ElemType e; int v1; v1=LocateVex(G,v); /* v1 为顶点 v 在图 G 中的序号 */ e.adjvex=LocateVex(G,w); /* e.adjvex 为顶点 w 在图 G 中的序号 */ p=Point(G.vertices[v1].firstarc,e,equalvex,&p1); /* p 指向顶点 v 的链表中邻接顶点为 w 的结 点 */ if(!p||!p->next) /* 没找到 w 或 w 是最后一个邻接点 */ return -1; else /* p->data.adjvex==w */ return p->next->data.adjvex; /* 返回 v 的(相对于 w 的)下一个邻接顶点的序号 */ } //注:下面的内容有点小复杂,应该考不到吧。有兴趣的可以看一下。 void InsertVex(ALGraph *G,VertexType v) { /* 初始条件:图 G 存在,v 和图中顶点有相同特征 */ /* 操作结果:在图 G 中增添新顶点 v(不增添与顶点相关的弧,留待 InsertArc()去做) */ 3
  • 4. strcpy((*G).vertices[(*G).vexnum].data,v); /* 构造新顶点向量 */ (*G).vertices[(*G).vexnum].firstarc=NULL; (*G).vexnum++; /* 图 G 的顶点数加 1 */ } Status DeleteVex(ALGraph *G,VertexType v) { /* 初始条件: G 存在, 是 G 中某个顶点。 图 v 操作结果:删除 G 中顶点 v 及其相关的弧 */ int i,j,k; ElemType e; LinkList p,p1; j=LocateVex(*G,v); /* j 是顶点 v 的序号 */ if(j<0) /* v 不是图 G 的顶点 */ return ERROR; i=ListLength((*G).vertices[j].firstarc); /* 以 v 为出度的弧或边数,在 bo2-8.c 中 */ (*G).arcnum-=i; /* 边或弧数-i */ if((*G).kind%2) /* 网 */ while((*G).vertices[j].firstarc) /* 对应的弧或边链表不空 */ { ListDelete(&(*G).vertices[j].firstarc,1,&e); /* 删除链表的第 1 个结点,并将值赋给 e */ free(e.info); /* 释放动态生成的权值空间 */ } else /* 图 */ DestroyList(&(*G).vertices[i].firstarc); /* 销毁弧或边链表,在 bo2-8.c 中 */ (*G).vexnum--; /* 顶点数减 1 */ for(i=j;i<(*G).vexnum;i++) /* 顶点 v 后面的顶点前移 */ (*G).vertices[i]=(*G).vertices[i+1]; for(i=0;i<(*G).vexnum;i++) /* 删除以 v 为入度的弧或边且必要时修改表结点的顶点位置值 */ { e.adjvex=j; p=Point((*G).vertices[i].firstarc,e,equalvex,&p1); /* Point()在 func2-1.c 中 */ if(p) /* 顶点 i 的邻接表上有 v 为入度的结点 */ { if(p1) /* p1 指向 p 所指结点的前驱 */ p1->next=p->next; /* 从链表中删除 p 所指结点 */ else /* p 指向首元结点 */ (*G).vertices[i].firstarc=p->next; /* 头指针指向下一结点 */ if((*G).kind<2) /* 有向 */ { (*G).arcnum--; /* 边或弧数-1 */ if((*G).kind==1) /* 有向网 */ free(p->data.info); /* 释放动态生成的权值空间 */ } free(p); /* 释放 v 为入度的结点 */ 4
  • 5. } for(k=j+1;k<=(*G).vexnum;k++) /* 对于 adjvex 域>j 的结点,其序号-1 */ { e.adjvex=k; p=Point((*G).vertices[i].firstarc,e,equalvex,&p1); /* Point()在 func2-1.c 中 */ if(p) p->data.adjvex--; /* 序号-1(因为前移) */ } } return OK; } Status InsertArc(ALGraph *G,VertexType v,VertexType w) { /* 初始条件:图 G 存在,v 和 w 是 G 中两个顶点 */ /* 操作结果:在 G 中增添弧<v,w>,若 G 是无向的,则还增添对称弧<w,v> */ ElemType e; int i,j; i=LocateVex(*G,v); /* 弧尾或边的序号 */ j=LocateVex(*G,w); /* 弧头或边的序号 */ if(i<0||j<0) return ERROR; (*G).arcnum++; /* 图 G 的弧或边的数目加 1 */ e.adjvex=j; e.info=NULL; /* 初值 */ if((*G).kind%2) /* 网 */ { e.info=(int *)malloc(sizeof(int)); /* 动态生成存放权值的空间 */ printf("请输入弧(边)%s→%s 的权值: ",v,w); scanf("%d",e.info); } ListInsert(&(*G).vertices[i].firstarc,1,e); /* 将 e 插在弧尾的表头,在 bo2-8.c 中 */ if((*G).kind>=2) /* 无向,生成另一个表结点 */ { e.adjvex=i; /* e.info 不变 */ ListInsert(&(*G).vertices[j].firstarc,1,e); /* 将 e 插在弧头的表头 */ } return OK; } Status DeleteArc(ALGraph *G,VertexType v,VertexType w) { /* 初始条件:图 G 存在,v 和 w 是 G 中两个顶点 */ /* 操作结果:在 G 中删除弧<v,w>,若 G 是无向的,则还删除对称弧<w,v> */ int i,j; Status k; ElemType e; 5
  • 6. i=LocateVex(*G,v); /* i 是顶点 v(弧尾)的序号 */ j=LocateVex(*G,w); /* j 是顶点 w(弧头)的序号 */ if(i<0||j<0||i==j) return ERROR; e.adjvex=j; k=DeleteElem(&(*G).vertices[i].firstarc,&e,equalvex); /* 在 func2-1.c 中 */ if(k) /* 删除成功 */ { (*G).arcnum--; /* 弧或边数减 1 */ if((*G).kind%2) /* 网 */ free(e.info); if((*G).kind>=2) /* 无向,删除对称弧<w,v> */ { e.adjvex=i; DeleteElem(&(*G).vertices[j].firstarc,&e,equalvex); } return OK; } else /* 没找到待删除的弧 */ return ERROR; } 6