数据结构C语言图邻接表存储表示和实现.docx

上传人:b****5 文档编号:8299899 上传时间:2023-01-30 格式:DOCX 页数:22 大小:21.17KB
下载 相关 举报
数据结构C语言图邻接表存储表示和实现.docx_第1页
第1页 / 共22页
数据结构C语言图邻接表存储表示和实现.docx_第2页
第2页 / 共22页
数据结构C语言图邻接表存储表示和实现.docx_第3页
第3页 / 共22页
数据结构C语言图邻接表存储表示和实现.docx_第4页
第4页 / 共22页
数据结构C语言图邻接表存储表示和实现.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

数据结构C语言图邻接表存储表示和实现.docx

《数据结构C语言图邻接表存储表示和实现.docx》由会员分享,可在线阅读,更多相关《数据结构C语言图邻接表存储表示和实现.docx(22页珍藏版)》请在冰豆网上搜索。

数据结构C语言图邻接表存储表示和实现.docx

数据结构C语言图邻接表存储表示和实现

数据结构C语言版图的邻接表存储表示和实现.txt如果青春的时光在闲散中度过,那么回忆岁月将是一场凄凉的悲剧。

杂草多的地方庄稼少,空话多的地方智慧少。

即使路上没有花朵,我仍可以欣赏荒芜。

/*

数据结构C语言版图的邻接表存储表示和实现

P163

编译环境:

Dev-C++4.9.9.2

日期:

2011年2月15日

*/

#include

//图的邻接表存储表示

#defineMAX_NAME3//顶点字符串的最大长度+1

#defineMAX_VERTEX_NUM20

typedefintInfoType;//存放网的权值

typedefcharVertexType[MAX_NAME];//字符串类型

typedefenum{DG,DN,AG,AN}GraphKind;//{有向图,有向网,无向图,无向网}

typedefstructArcNode

{

intadjvex;//该弧所指向的顶点的位置

structArcNode*nextarc;//指向下一条弧的指针

InfoType*info;//网的权值指针)

}ArcNode;//表结点

typedefstructVNode

{

VertexTypedata;//顶点信息

ArcNode*firstarc;//第一个表结点的地址,指向第一条依附该顶点的弧的指针

}VNode,AdjList[MAX_VERTEX_NUM];//头结点

typedefstruct

{

AdjListvertices;

intvexnum,arcnum;//图的当前顶点数和弧数

intkind;//图的种类标志

}ALGraph;

typedefintQElemType;//队列类型

//单链队列--队列的链式存储结构

typedefstructQNode

{

QElemTypedata;//数据域

structQNode*next;//指针域

}QNode,*QueuePtr;

typedefstruct

{

QueuePtrfront,//队头指针,指针域指向队头元素

rear;//队尾指针,指向队尾元素

}LinkQueue;

//若G中存在顶点u,则返回该顶点在图中位置;否则返回-1。

intLocateVex(ALGraphG,VertexTypeu)

{

inti;

for(i=0;i

if(strcmp(u,G.vertices[i].data)==0)

returni;

return-1;

}

//采用邻接表存储结构,构造没有相关信息的图G(用一个函数构造4种图)。

intCreateGraph(ALGraph*G)

{

inti,j,k;

intw;//权值

VertexTypeva,vb;

ArcNode*p;

printf("请输入图的类型(有向图:

0,有向网:

1,无向图:

2,无向网:

3):

");

scanf("%d",&(*G).kind);

printf("请输入图的顶点数和边数:

(空格)\n");

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

printf("请输入%d个顶点的值(<%d个字符):

\n",(*G).vexnum,MAX_NAME);

for(i=0;i<(*G).vexnum;++i)//构造顶点向量

{

scanf("%s",(*G).vertices[i].data);

(*G).vertices[i].firstarc=NULL;

}

if((*G).kind==1||(*G).kind==3)//网

printf("请顺序输入每条弧(边)的权值、弧尾和弧头(以空格作为间隔):

\n");

else//图

printf("请顺序输入每条弧(边)的弧尾和弧头(以空格作为间隔):

\n");

for(k=0;k<(*G).arcnum;++k)//构造表结点链表

{

if((*G).kind==1||(*G).kind==3)//网

scanf("%d%s%s",&w,va,vb);

else//图

scanf("%s%s",va,vb);

i=LocateVex(*G,va);//弧尾

j=LocateVex(*G,vb);//弧头

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

p->adjvex=j;

if((*G).kind==1||(*G).kind==3)//网

{

p->info=(int*)malloc(sizeof(int));

*(p->info)=w;

}

else

p->info=NULL;//图

p->nextarc=(*G).vertices[i].firstarc;//插在表头

(*G).vertices[i].firstarc=p;

if((*G).kind>=2)//无向图或网,产生第二个表结点

{

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

p->adjvex=i;

if((*G).kind==3)//无向网

{

p->info=(int*)malloc(sizeof(int));

*(p->info)=w;

}

else

p->info=NULL;//无向图

p->nextarc=(*G).vertices[j].firstarc;//插在表头

(*G).vertices[j].firstarc=p;

}

}

return1;

}

//销毁图G。

voidDestroyGraph(ALGraph*G)

{

inti;

ArcNode*p,*q;

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

{

p=(*G).vertices[i].firstarc;

while(p)

{

q=p->nextarc;

if((*G).kind%2)//网

free(p->info);

free(p);

p=q;

}

}

(*G).vexnum=0;

(*G).arcnum=0;

}

//返回v的值。

VertexType*GetVex(ALGraphG,intv)

{

if(v>=G.vexnum||v<0)

exit(0);

return&G.vertices[v].data;

}

//对v赋新值value。

intPutVex(ALGraph*G,VertexTypev,VertexTypevalue)

{

inti;

i=LocateVex(*G,v);

if(i>-1)//v是G的顶点

{

strcpy((*G).vertices[i].data,value);

return1;

}

return0;

}

//返回v的第一个邻接顶点的序号。

若顶点在G中没有邻接顶点,则返回-1。

intFirstAdjVex(ALGraphG,VertexTypev)

{

ArcNode*p;

intv1;

v1=LocateVex(G,v);//v1为顶点v在图G中的序号

p=G.vertices[v1].firstarc;

if(p)

returnp->adjvex;

else

return-1;

}

//返回v的(相对于w的)下一个邻接顶点的序号。

若w是v的最后一个

//邻接点,则返回-1。

intNextAdjVex(ALGraphG,VertexTypev,VertexTypew)

{

ArcNode*p;

intv1,w1;

v1=LocateVex(G,v);//v1为顶点v在图G中的序号

w1=LocateVex(G,w);//w1为顶点w在图G中的序号

p=G.vertices[v1].firstarc;

while(p&&p->adjvex!

=w1)//指针p不空且所指表结点不是w

p=p->nextarc;

if(!

p||!

p->nextarc)//没找到w或w是最后一个邻接点

return-1;

else//p->adjvex==w

//返回v的(相对于w的)下一个邻接顶点的序号

returnp->nextarc->adjvex;

}

//在图G中增添新顶点v(不增添与顶点相关的弧,留待InsertArc()去做)。

voidInsertVex(ALGraph*G,VertexTypev)

{

strcpy((*G).vertices[(*G).vexnum].data,v);//构造新顶点向量

(*G).vertices[(*G).vexnum].firstarc=NULL;

(*G).vexnum++;//图G的顶点数加1

}

//删除G中顶点v及其相关的弧。

intDeleteVex(ALGraph*G,VertexTypev)

{

inti,j;

ArcNode*p,*q;

j=LocateVex(*G,v);//j是顶点v的序号

if(j<0)//v不是图G的顶点

return0;

p=(*G).vertices[j].firstarc;//删除以v为出度的弧或边

while(p)

{

q=p;

p=p->nextarc;

if((*G).kind%2)//网

free(q->info);

free(q);

(*G).arcnum--;//弧或边数减1

}

(*G).vexnum--;//顶点数减1

for(i=j;i<(*G).vexnum;i++)//顶点v后面的顶点前移

(*G).vertices[i]=(*G).vertices[i+1];

//删除以v为入度的弧或边且必要时修改表结点的顶点位置值

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

{

p=(*G).vertices[i].firstarc;//指向第1条弧或边

while(p)//有弧

{

if(p->adjvex==j)//是以v为入度的边。

{

if(p==(*G).vertices[i].firstarc)//待删结点是第1个结点

{

(*G).vertices[i].firstarc=p->nextarc;

if((*G).kind%2)//网

free(p->info);

free(p);

p=(*G).vertices[i].firstarc;

if((*G).kind<2)//有向

(*G).arcnum--;//弧或边数减1

}

else

{

q->nextarc=p->nextarc;

if((*G).kind%2)//网

free(p->info);

free(p);

p=q->nextarc;

if((*G).kind<2)//有向

(*G).arcnum--;//弧或边数减1

}

}

else

{

if(p->adjvex>j)

p->adjvex--;//修改表结点的顶点位置值(序号)

q=p;

p=p->nextarc;

}

}

}

return1;

}

//在G中增添弧,若G是无向的,则还增添对称弧

intInsertArc(ALGraph*G,VertexTypev,VertexTypew)

{

ArcNode*p;

intw1,i,j;

i=LocateVex(*G,v);//弧尾或边的序号

j=LocateVex(*G,w);//弧头或边的序号

if(i<0||j<0)

return0;

(*G).arcnum++;//图G的弧或边的数目加1

if((*G).kind%2)//网

{

printf("请输入弧(边)%s→%s的权值:

",v,w);

scanf("%d",&w1);

}

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

p->adjvex=j;

if((*G).kind%2)//网

{

p->info=(int*)malloc(sizeof(int));

*(p->info)=w1;

}

else

p->info=NULL;

p->nextarc=(*G).vertices[i].firstarc;//插在表头

(*G).vertices[i].firstarc=p;

if((*G).kind>=2)//无向,生成另一个表结点

{

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

p->adjvex=i;

if((*G).kind==3)//无向网

{

p->info=(int*)malloc(sizeof(int));

*(p->info)=w1;

}

else

p->info=NULL;

p->nextarc=(*G).vertices[j].firstarc;//插在表头

(*G).vertices[j].firstarc=p;

}

return1;

}

//在G中删除弧,若G是无向的,则还删除对称弧

intDeleteArc(ALGraph*G,VertexTypev,VertexTypew)

{

ArcNode*p,*q;

inti,j;

i=LocateVex(*G,v);//i是顶点v(弧尾)的序号

j=LocateVex(*G,w);//j是顶点w(弧头)的序号

if(i<0||j<0||i==j)

return0;

p=(*G).vertices[i].firstarc;//p指向顶点v的第一条出弧

while(p&&p->adjvex!

=j)//p不空且所指之弧不是待删除弧

{//p指向下一条弧

q=p;

p=p->nextarc;

}

if(p&&p->adjvex==j)//找到弧

{

if(p==(*G).vertices[i].firstarc)//p所指是第1条弧

(*G).vertices[i].firstarc=p->nextarc;//指向下一条弧

else

q->nextarc=p->nextarc;//指向下一条弧

if((*G).kind%2)//网

free(p->info);

free(p);//释放此结点

(*G).arcnum--;//弧或边数减1

}

if((*G).kind>=2)//无向,删除对称弧

{

p=(*G).vertices[j].firstarc;//p指隙サ鉾的第一条出弧

while(p&&p->adjvex!

=i)//p不空且所指之弧不是待删除弧

{//p指向下一条弧

q=p;

p=p->nextarc;

}

if(p&&p->adjvex==i)//找到弧

{

if(p==(*G).vertices[j].firstarc)//p所指是第1条弧

(*G).vertices[j].firstarc=p->nextarc;//指向下一条弧

else

q->nextarc=p->nextarc;//指向下一条弧

if((*G).kind==3)//无向网

free(p->info);

free(p);//释放此结点

}

}

return1;

}

intvisited[MAX_VERTEX_NUM];//访问标志数组(全局量)

void(*VisitFunc)(char*v);//函数变量(全局量)

//算法7.5P169

//从第v个顶点出发递归地深度优先遍历图G。

voidDFS(ALGraphG,intv)

{

intw;

VertexTypev1,w1;

strcpy(v1,*GetVex(G,v));

visited[v]=1;//设置访问标志为1(已访问)

VisitFunc(G.vertices[v].data);//访问第v个顶点

for(w=FirstAdjVex(G,v1);w>=0;

w=NextAdjVex(G,v1,strcpy(w1,*GetVex(G,w))))

if(!

visited[w])

DFS(G,w);//对v的尚未访问的邻接点w递归调用DFS

}

//算法7.4P169

//对图G作深度优先遍历。

voidDFSTraverse(ALGraphG,void(*Visit)(char*))

{

intv;

//使用全局变量VisitFunc,使DFS不必设函数指针参数

VisitFunc=Visit;

for(v=0;v

visited[v]=0;//访问标志数组初始化

for(v=0;v

if(!

visited[v])

DFS(G,v);//对尚未访问的顶点调用DFS

printf("\n");

}

//构造一个空队列Q。

intInitQueue(LinkQueue*Q)

{

(*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));//动态分配一个空间

if(!

(*Q).front)

exit(0);

(*Q).front->next=NULL;//队头指针指向空,无数据域,这样构成了一个空队列

return1;

}

//插入元素e为Q的新的队尾元素。

intEnQueue(LinkQueue*Q,QElemTypee)

{

QueuePtrp=(QueuePtr)malloc(sizeof(QNode));

if(!

p)//存储分配失败

exit(0);

//生成一个以为e为数据域的队列元素

p->data=e;

p->next=NULL;

//将该新队列元素接在队尾的后面

(*Q).rear->next=p;

(*Q).rear=p;

return1;

}

//若队列不空,删除Q的队头元素,用e返回其值,并返回1,否则返回0。

intDeQueue(LinkQueue*Q,QElemType*e)

{

QueuePtrp;

if((*Q).front==(*Q).rear)

return0;

p=(*Q).front->next;//队头元素

*e=p->data;

(*Q).front->next=p->next;

if((*Q).rear==p)

(*Q).rear=(*Q).front;

free(p);

return1;

}

//若Q为空队列,则返回1,否则返回0。

intQueueEmpty(LinkQueueQ)

{

if(Q.front==Q.rear)

return1;

else

return0;

}

//算法7.6P170

//按广度优先非递归遍历图G。

使用辅助队列Q和访问标志数组visited。

voidBFSTraverse(ALGraphG,void(*Visit)(char*))

{

intv,u,w;

VertexTypeu1,w1;

LinkQueueQ;

for(v=0;v

visited[v]=0;//置初值

InitQueue(&Q);//置空的辅助队列Q

for(v=0;v

if(!

visited[v])//v尚未访问

{

visited[v]=1;

Visit(G.vertices[v].data);

EnQueue(&Q,v);//v入队列

while(!

QueueEmpty(Q))//队列不空

{

DeQueue(&Q,&u);//队头元素出队并置为u

strcpy(u1,*GetVex(G,u));

for(w=FirstAdjVex(G,u1);w>=0;w=NextAdjVex(G,

u1,strcpy(w1,*GetVex(G,w))))

if(!

visited[w])//w为u的尚未访问的邻接顶点

{

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 起诉状

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1