#include 邻接表表示的图的基本操作的实现//采用邻接表完成无权无向及有向图的"建立、输出、深度遍历、广度遍历"操作#include <stdio.h>#include <stdlib.h>#define OK 1#define ERROR -1typedef int Status;typedef int ElemType; //此例中设元素为单值元素,类型为整型#define MAX_VERTEX_NUM 20 //最大顶点个数typedef int ElemType; //图顶点数据类型typedef int QueueElemType;//队列结点数据类型//链表结点类型定义typedef struct Qnode{QueueElemType data;struct Qnode *next;}QNode;//队列类型定义:typedef struct Linkqueue{QNode *front,*rear;}LinkQueue;//图的数据类型定义typedef struct Tablenode//表结点结构{int adjVex;//邻接点域,存放与vi相邻接的顶点vj的序号jstruct Tablenode *next;//指针域,将邻接表的所有表结点链在一起float weight;//对于带权图,表示权值,对于无权图则可省略此数据域}TableNode;typedef struct Headnode//头结点结构{ElemType vertex;//顶点域vertex,存放顶点vi的信息struct Tablenode *firstEdge;//vi的邻接表的头指针}HeadNode;typedef struct Mgraph{struct Headnode vector[MAX_VERTEX_NUM]; //顶点向量int vexnum; //图中当前顶点数} MGraph;//队列初始化Status InitLinkQueue(LinkQueue *Q){QNode *p;p=(QNode*)malloc(sizeof(QNode));//开辟头结点空间if(p!=NULL){p->next=NULL;Q->front=Q->rear=p;return OK;}elsereturn ERROR;}//链式队列的入队操作,在已知队列的队尾插入一个元素e,修改队尾指针rear。 Status InsertLinkQueue(LinkQueue *Q,ElemType e){QNode *p;p=(QNode*)malloc(sizeof(QNode));if(p==NULL)return ERROR;//申请新结点空间失败,返回错误标志else{p->data=e;//存入新结点数据p->next=NULL;Q->rear->next=p;//新结点插入到队尾Q->rear=p;//新插入结点成为新的队尾return OK;}}//链式队列的出队操作,取第一个数据结点的数据后删除该结点Status DeleteLinkQueue(LinkQueue *Q,ElemType *e){QNode *p;if(Q->front==Q->rear)//可改为:if(Q->front->next==NULL)return ERROR;//队空else{p=Q->front->next;//取队首结点*e=p->data;Q->front->next=p->next;//修改队首指针if(p==Q->rear)//条件成立说明只有一个数据结点Q->rear=Q->front;//当队列只有一个数据结点时应防止丢失队尾指针free(p);Q->rear->next=NULL;return OK;}}//判断队列是否为空Status IsEmptyLinkQueue(LinkQueue *Q){if(Q->front==Q->rear)return OK;elsereturn ERROR;}//释放队列void DestroyLinkQueue(LinkQueue *Q){QNode *p,*q;p=Q->front;//指向链表第一个结点,即整个链表的第一个结点while(p!=NULL){q=p->next;//保存链表后半段首地址以防丢失free(p);p=q;}}/**************以下为图的操作************///顶点在顶点向量中的定位,找到返回OK,否则返回ERROR//G为的数据结构,v为待查顶点,n用于返回找到的顶点下标Status LocateVex(MGraph G,ElemType v,int *n){int i;for(i=0;((i<G.vexnum)&&(G.vector[i].vertex!=v));i++) ;*n=i;if(i<G.vexnum)return OK;elsereturn ERROR;}//建立无向图的邻接表void CreateGraph(MGraph *G){int i,k;Status sfjx;TableNode *p,*q;ElemType v;printf("请输入图的顶点数:");scanf("%d",&(G->vexnum));printf("请输入%d个顶点信息:\n",G->vexnum);for(i=0;i<G->vexnum;i++) //输入顶点向量scanf("%d",&(G->vector[i].vertex));printf("顶点向量如下:\n"); //输出顶点向量for(i=0;i<G->vexnum;i++)printf("%4d",G->vector[i].vertex);printf("\n请逐个输入无权图各顶点的邻接点(输入不存在的邻接点则表示结束):\n");for(k=0;k<G->vexnum;k++) //输入无权图的邻接点{printf("请输入顶点%d的邻接点:",G->vector[k].vertex);G->vector[k].firstEdge=(TableNode*)malloc(sizeof(TableNode));q=G->vector[k].firstEdge;fflush(stdin);do{scanf("%d",&v);sfjx=LocateVex(*G,v,&i);if(sfjx==OK){p=(TableNode *)malloc(sizeof(TableNode));if(p!=NULL){p->adjVex=i;q->next=p;q=p;}}}while(sfjx==OK);q->next=NULL;}}//输出无向图的邻接表void PrintGraph(MGraph G){int i;TableNode *p;printf("图信息如下:\n");for(i=0;i<G.vexnum;i++){printf("%4d:",G.vector[i].vertex);p=G.vector[i].firstEdge->next;while(p!=NULL){printf("%4d",p->adjVex);p=p->next;}printf("\n");}}//查找顶点v的第一个邻接点,v为当前顶点下标int FirstAdjVex(MGraph G,int v){int p=-1;TableNode *q;q=G.vector[v].firstEdge->next;if(q!=NULL)p=q->adjVex;return p;}//查找顶点v的下一个邻接点,w为当前邻接点下标int NextAdjVex(MGraph G,int v,int w){int p=-1;TableNode *q;q=G.vector[v].firstEdge->next;while((q!=NULL)&&(q->adjVex!=w))q=q->next;if(q!=NULL){q=q->next;if(q!=NULL)p=q->adjVex;}return p;}//深度优先遍历char visited[MAX_VERTEX_NUM];//访问标志数组void Dfs(MGraph G,int v){int w;visited[v]=1;printf("%4d",G.vector[v]);for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w)) if(visited[w]==0)Dfs(G,w);}void DfsTraverse(MGraph G){int v;for(v=0;v<G.vexnum;v++)visited[v]=0;for(v=0;v<G.vexnum;v++)if(visited[v]==0)Dfs(G,v);}//广度优先遍历void BfsTraverse(MGraph G){int v,u,w;LinkQueue Q;for(v=0;v<G.vexnum;v++)visited[v]=0;InitLinkQueue(&Q);for(v=0;v<G.vexnum;v++)if(visited[v]==0){visited[v]=1;printf("%4d",G.vector[v]);InsertLinkQueue(&Q,v);while(IsEmptyLinkQueue(&Q)!=OK){DeleteLinkQueue(&Q,&u);for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w))if(visited[w]==0){visited[w]=1;printf("%4d",G.vector[w]);InsertLinkQueue(&Q,w);}}}DestroyLinkQueue(&Q);}//主函数void main(){int xz=1;MGraph G;while(xz!=0){printf("1-输入图信息\n");printf("2-输出图信息\n");printf("3-图的深度优先遍历\n");printf("4-图的广度优先遍历\n");printf("0-退出\n请选择:");fflush(stdin);scanf("%d",&xz);switch(xz){case 1:CreateGraph(&G);break;case 2:PrintGraph(G);break;case 3:DfsTraverse(G);printf("\n");break;case 4:BfsTraverse(G);printf("\n");break;case 0:printf("再见!\n");break;default:printf("输入错误!\n");break;}}}。邻接表表示的图的基本操作的实现