您的位置:首页 > 其它

有向图的十字链表存储表示 以及相关操作(包括增加弧、删除弧、删除顶点等)

2013-11-29 07:07 465 查看
十字链表表示特点


















1.针对弧结点,增加入弧链表结构和出弧链表结构;
2.容易求得任意顶点的出度和入度,专用于有向图的操作;
3.结构实现比较复杂。

基本数据结构

1.弧的数据结构
typedef struct OLGArc

{

int tailvex;

int headvex;

struct OLGArc *hlink;

struct OLGArc *tlink;

}OLGArc;

2.顶点结构
typedef struct VexNode

{

char data;

OLGArc *firstin;

OLGArc *firstout;

}OLGVNode;

3.图的十字链表表示
typedef struct

{

OLGVNode xlist[MAX_VERTEX_NUM];

int vexnum;

int arcnum;

}OLGraph;

有向图的十字链表表示的相关操作

1.求图中某顶点在顶点数组中的下标
int LocateVex(OLGraph G,char x)

{

int i;

for(i=0;i<G.vexnum;++i)

if(G.xlist[i].data==x)

return i;

return -1;

}

2.创建有向图的十字链表存储表示
void CreateOLGraph(OLGraph &G)

{

int i,j,k;

char u,v;

//printf("input vexnum of G\n");

scanf("%d",&G.vexnum);

//printf("input arcnum of G\n");

scanf("%d",&G.arcnum);

printf("input value of each vertex of G\n"); // initial vertex array

getchar();

for(i=0;i<G.vexnum;++i)

{

scanf("%c",&G.xlist[i].data); //such as A B C D ,There is a blank between two vertex when you input data

if(i!=G.vexnum - 1)

getchar(); //eat the blank

G.xlist[i].firstin=NULL;

G.xlist[i].firstout=NULL;

}

printf("input the information of arc of G\n");

for(k=0;k<G.arcnum;++k)

{

scanf("%c %c",&u,&v);

getchar(); //eat the \n

i=LocateVex(G,u);

j=LocateVex(G,v);

OLGArc *p;

p=(OLGArc*)malloc(sizeof(OLGArc)); // apply a new save space

p->tailvex=i;

p->headvex=j;

p->hlink=G.xlist[j].firstin;

p->tlink=G.xlist[i].firstout;

G.xlist[i].firstout=p;

G.xlist[j].firstin=p;

}

}

3.十字链表存储表示的有向图的打印输出
void Display(OLGraph G)

{

int i,j,k;

OLGArc *p;

for(i=0;i<G.vexnum;++i)

printf("%c\t",G.xlist[i].data);

printf("\n");

for(i=0;i<G.vexnum;++i)

{

for(p=G.xlist[i].firstout;p!=NULL;p=p->tlink)

printf("%c--->%c\t",G.xlist[i].data,G.xlist[p->headvex].data);

}

printf("\n");

}

4.在有向图中插入一条新的弧
void InsertArc(OLGraph &G,char u,char v)

{

int i,j;

OLGArc *p;

i=LocateVex(G,u);

j=LocateVex(G,v);

p=(OLGArc*)malloc(sizeof(OLGArc));

p->headvex=j;

p->tailvex=i;

p->hlink=G.xlist[j].firstin;

p->tlink=G.xlist[i].firstout;

G.xlist[i].firstout=p;

G.xlist[j].firstin=p;

G.arcnum++;

}

5.在有向图中删除一条弧
void DeleteArc(OLGraph &G,char u,char v)

{

int i,j;

OLGArc *p,*q;

i=LocateVex(G,u);

j=LocateVex(G,v);

//修改u的出弧链表

if(G.xlist[i].firstout->headvex==j)

{

q=G.xlist[i].firstout;

G.xlist[i].firstout=q->tlink;

G.arcnum--;

}

else

{

for(p=G.xlist[i].firstout;p&&(p->tlink!=NULL)&&(p->tlink->headvex!=j);p=p->tlink);

if(p&&p->tlink) //之前没有加p->tlink!=NULL,若p->tlink==NULL,则q==NULL,q->tlink也就无意义了,同上差不多,会造成各种指针错误

{

q=p->tlink;

p->tlink=q->tlink;

G.arcnum--;

}

}

//修改v的入弧链表

if(G.xlist[j].firstin->tailvex==i)

{

q=G.xlist[j].firstin;

G.xlist[j].firstin=q->hlink;

free(q);

}

else

{

for(p=G.xlist[j].firstin;p&&(p->hlink)&&(p->hlink->tailvex!=i);p=p->hlink);

if(p&&p->hlink)

{

q=p->hlink;

p->hlink=q->hlink;

free(q);

}

}

}
6.删除有向图中的一个顶点
顶点删除分两步删除与v相关的弧
首先删除顶点v的所有入弧,这些弧结点分散于其他顶点的出弧链表中,同时也构成了顶点v的入弧链表。
在删除顶点v的入弧结点时不用维护顶点v入弧链表的连通性,但要维护该弧结点所在的其他顶点出弧链表的连通性。
void DeleteVex(OLGraph &G,char v)

{

int k=LocateVex(G,v);

int i,j;

OLGArc* p=NULL;

OLGArc* q=NULL;

for(j=0;j<G.vexnum;j++) //遍历所有结点的出弧链表,找到待删的弧结点(以v作为弧头结点的弧的结点),修改每个结点的要修改处的指针,保持目标结点被删除后仍保持原有的连通性

{

if(G.xlist[j].firstout==NULL) //该顶点没有出弧链表

continue;

else

{

if(G.xlist[j].firstout->headvex==k) //出弧链表的第一个结点恰好是要删除的结点

{

q=G.xlist[j].firstout;

G.xlist[j].firstout=q->tlink;

G.arcnum--;

}

else

{ //遍历链表找到要删除的弧的结点,其中(p->tlink!=NULL),之前没有加上,造成潜在隐患,若p->tlink==NULL,则p->tlink->headvex无效的引用

for(p=G.xlist[j].firstout;p&&(p->tlink!=NULL)&&(p->tlink->headvex!=k);p=p->tlink);

if(p&&p->tlink) //之前没有加p->tlink!=NULL,若p->tlink==NULL,则q==NULL,q->tlink也就无意义了,同上差不多,会造成各种指针错误

{

q=p->tlink;

p->tlink=q->tlink;

G.arcnum--;

}

}

}

}

//删除v的出弧链表和入弧链表

p=G.xlist[k].firstout;

while(p)

{

q=p;

p=p->tlink;

free(q);

}

p=G.xlist[k].firstin;

while(p)

{

q=p;

p=p->hlink;

free(q);

}

for(j=k+1;j<G.vexnum;j++) //数组前移

G.xlist[j-1]=G.xlist[j];

G.vexnum--; //顶点数减一

for(j=0;j<G.vexnum;j++)

{

for(p=G.xlist[j].firstout;p;p=p->tlink)

{

if(p->tailvex>k)

p->tailvex--;

if(p->headvex>k)

p->headvex--;

}

}

}

int main()

{

OLGraph G;

char u,v;

CreateOLGraph(G);

Display(G);

printf("input newly inserted arc\n");

scanf("%c %c",&u,&v);

InsertArc(G,u,v);

Display(G);

printf("input to be deleted vertex:\n");

getchar();

scanf("%c",&u);

DeleteVex(G,u);

Display(G);

printf("input to be deleted arc:\n");

getchar();

scanf("%c %c",&u,&v);

DeleteArc(G,u,v);

Display(G);

return 0;

}

//测试数据(创建一个有向图的十字链表存储表示) (测试数据对应于本文的第一幅图片)

/*

4

7

A B C D

A B

A C

C A

C D

D A

D B

D C

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐