More Related Content
More from mengyingchina (7)
数据结构复习笔记 图的邻接表存储表示及重要的基本操作
- 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