当前位置:文档之家› 数据结构实习三 图及其应用

数据结构实习三 图及其应用

数据结构学院:姓名:班级:学号:实习三图及其应用题目:试设计一个算法,求图中一个源点到其他各顶点的最短路径。

一.需求分析:设计要求:(1)用邻接表表示图;(2)按长度非递减次序打印输出最短路径的长度及相应路径。

二.设计思想:本程序使用链表的形式存储的。

根据书上的德克斯德拉算法的思想,初始状态时,集合s中只包含源点,设为v0,然后不断地从集合T中选择到源点v0路径长度最短的结点u加入到集合s中,集合s中每加入一个新的结点u都要修改从源点v0到集合T中剩余结点的当前最短路径长度值,集合T中各结点的新的当前最短路径的长度值,为原来的最短路径的长度值与从源点过结点u到达该结点的路径长度中的最小者。

此过程不断地重复,直到集合T中的结点全部加入到集合s中为止。

三.设计提示题中规定采用邻接表表示图,假设图中有n个顶点,则考虑邻接表表头结点为head[0],head[1],head[2],…,head[n-1],链表中每个结点有三个字段:其中,vertex——顶点字段,存放顶点序号;cost——表头顶点到该顶点之边上的权值;link——连接同一链中的下一个顶点。

采用数组dist[j](0≤j≤n-1)存放从源点v0到顶点vj的最短路径长度,dist[0]=0,如果源点v0到顶点vx无通路,则dist[x]=max(计算机允许的最大值)。

采用n-1个数组分别存放源点v0到其余n-1个顶点之最短路径上的顶点(序号)。

采用数组S指示已找到最短路径的顶点。

S[j]=0表示顶点j不在数组中,S[j]=1表示顶点j在数组中(0≤j≤n-1)。

四.设计思想构图比较简单。

求最短路径是修改的书上的Dijkstra 函数,书上的图是用邻接矩阵存储的,我按照题目要求改为邻接链表,但是思想一样。

排序借用了冒泡排序法。

输出最短路径是自己设计的一个递归函数。

函数体如下:void Dijkstra(AdjLGraph G, int v0, int distance[], int path[]) /*带权图G 从下标v0顶点到其它顶点的最短距离distance*/ /*和最短路径下标path*/ { Edge *p;int n=G.numOfVerts;int *s = (int *)malloc(sizeof(int)*n); int minDis, i,j,u; /*初始化*/for(i = 0; i < n; i ++)构图 求最短路径打印输入点边信息调用creatgraph排序输出(可用递归){ distance[i] =MaxWeight;s[i] = 0;path[i] = -1;}distance[v0]=0;p=G.a[v0].adj;while(p!=NULL){distance[p->dest]=p->cost;path[p->dest]=G.a[v0].data;p=p->next;}s[v0] = 1;/*在还未找到最短路径的顶点集中选有最短距离的顶点u*/for(i = 1; i < n; i ++){ minDis = MaxWeight;for(j = 0;j <=n;j ++)if(s[j] == 0 && distance[j] < minDis){ u = j; minDis = distance[j]; }/*当已不再存在路径时算法结束*/if(minDis == MaxWeight) return;s[u] = 1; /*标记顶点u已从集合T加入到集合S中*//*修改从v0到其它顶点的最短距离和最短路径*/p=G.a[u].adj;while(p!=NULL){if(s[p->dest] == 0 && distance[u] +p->cost < distance[p->dest]){ distance[p->dest] = distance[u] +p->cost;path[p->dest] =G.a[u].data;}p=p->next;}}}void printpath(int i,int start,int path[],int a[]){int j,u;u=0;if(path[i]==start) {printf("%d",start); return;}for(j=0;j<6;j++){if(a[j]!=path[i]){u++;}if(a[j]!=path[i])break;}printpath(u,start,path,a); printf("%d",path[i]);}源代码:#include <stdio.h>#include <malloc.h>typedef int DataType;#define MaxSize 100#define MaxVertices 10#define MaxEdges 100#define MaxWeight 10000//********邻接表的存储结构***********typedef struct Node{ int cost;int dest; /*邻接边的弧头顶点序号*/struct Node *next;}Edge; /*邻接边单链表的结点结构体*/typedef struct{DataType data; /*顶点数据元素*/int source; /*邻接边的弧尾顶点序号*/Edge *adj; /*邻接边的头指针*/} AdjLHeight; /*数组的数据元素类型结构体*/typedef struct{AdjLHeight a[MaxVertices]; /*邻接表数组*/int numOfVerts; /*顶点个数*/int numOfEdges; /*边个数*/} AdjLGraph;/*邻接表结构体*/typedef struct{int row;int col;int weight;}RowCol;void AdjInitiate(AdjLGraph *G){int i;G->numOfVerts=0;G->numOfEdges=0;for(i=0;i<MaxVertices;i++){G->a[i].source=1;G->a[i].adj=NULL;}}void InsertVertex(AdjLGraph *G,int i,DataType vertex) {if(i>=0&&i<MaxVertices){G->a[i].data=vertex;G->numOfVerts++;}else printf("定点越界");}void InsertEdge(AdjLGraph *G,int v1,int v2,int cost) {Edge *p;if (v1<0||v1>=G->numOfVerts||v2<0||v2>=G->numOfVerts) { printf("v1 or v2越界");return ;}p=(Edge *)malloc(sizeof(Edge));p->dest=v2;p->cost=cost;p->next=G->a[v1].adj;G->a[v1].adj=p;G->numOfEdges++;}int GeFirstVex(AdjLGraph *G,int v){Edge *p;if (v<0||v>=G->numOfVerts){ printf("v越界");return -1;}p=G->a[v].adj;if(p!=NULL)return p->dest;else return -1;}int GetNextVex(AdjLGraph *G,int v1,const int v2) {Edge *p;if (v1<0||v1>=G->numOfVerts||v2<0||v2>=G->numOfVerts) { printf("v1 or v2越界");return -1;}p=G->a[v1].adj;while(p!=NULL){if(p->dest!=v2){p=p->next;continue;}else break;}p=p->next;if(p!=NULL)return p->dest;else return -1;}void CreateGraph(AdjLGraph *G,DataType v[],int n,RowCol d[],int e){int i,k;AdjInitiate(G);for(i=0;i<n;i++)InsertVertex(G, i,v[i]);for(k=0;k<e;k++)InsertEdge(G,d[k].row,d[k].col,d[k].weight);}/*zhunbeigongzuo*///8888888888888888888888888888888888888888888888888888888888888888888888 8888888void Dijkstra(AdjLGraph G, int v0, int distance[], int path[])/*带权图G从下标v0顶点到其它顶点的最短距离distance*//*和最短路径下标path*/{ Edge *p;int n=G.numOfVerts;int *s = (int *)malloc(sizeof(int)*n);int minDis, i,j,u;/*初始化*/for(i = 0; i < n; i ++){ distance[i] =MaxWeight;s[i] = 0;path[i] = -1;}distance[v0]=0;p=G.a[v0].adj;while(p!=NULL){distance[p->dest]=p->cost;path[p->dest]=G.a[v0].data;p=p->next;}s[v0] = 1;/*在还未找到最短路径的顶点集中选有最短距离的顶点u*/for(i = 1; i < n; i ++){ minDis = MaxWeight;for(j = 0;j <=n;j ++)if(s[j] == 0 && distance[j] < minDis){ u = j; minDis = distance[j]; }/*当已不再存在路径时算法结束*/if(minDis == MaxWeight) return;s[u] = 1; /*标记顶点u已从集合T加入到集合S中*//*修改从v0到其它顶点的最短距离和最短路径*/p=G.a[u].adj;while(p!=NULL){if(s[p->dest] == 0 && distance[u] +p->cost < distance[p->dest]){ distance[p->dest] = distance[u] +p->cost;path[p->dest] =G.a[u].data;}p=p->next;}}}//8888888888888888888888888888888888888888888888888888888888888888888888 888888888888888888888888888//8888888888888888888888888888888888888888888888888888888888888void BubbleSort(DataType a[],int distance[],int path[],int n){int i,j,flag=1;DataType temp;for(i = 1;i < n && flag == 1; i++){flag = 0;for(j = 0;j < n - i; j++){ if(distance[j]>distance[j+1]){ flag = 1;temp = a[j];a[j] = a[j+1];a[j+1] = temp;temp = path[j];path[j] = path[j+1];path[j+1] = temp;temp = distance[j];distance[j] = distance[j+1];distance[j+1] = temp;}}}}void printpath(int i,int start,int path[],int a[]){int j,u;u=0;if(path[i]==start){printf("%d",start);return;}for(j=0;j<6;j++){if(a[j]!=path[i]){u++;}if(a[j]!=path[i])break;}printpath(u,start,path,a);printf("%d",path[i]);}//8888888888888888888888888888888888888888888888888888888888888888888888 8main(){AdjLGraph g1;int a[MaxVertices];RowCol row[MaxEdges];int i,j,k,v0;int distance[6],path[6];printf("请输入图的点的个数");scanf("%d",&i);printf("请输入图的边的个数");scanf("%d",&j);for(k=0;k<i;k++){printf("请输入图的点");scanf("%d",&a[k]);}for(k=0;k<j;k++){printf("请输入图的边终点在数组中的下标值");scanf("%d",&row[k].col);printf("请输入图的边起点在数组中的下标值");scanf("%d",&row[k].row);printf("请输入图的边的值\n");scanf("%d",&row[k].weight);}CreateGraph(&g1,a,i,row,j);printf("请输入起点在数组中的下标");scanf("%d",&v0);Dijkstra(g1,v0,distance,path);BubbleSort(a,distance,path,6);printf("从定点%d到其他个点的最短距离为:\n",a[0]); for(i=0;i<6;i++)printf("到顶点%d的最短距离为%d\n",a[i],distance[i]); for(i=1;i<6;i++){printf("到点%d的最短路径为\n",a[i]);printpath(i,a[0],path,a);printf("%d",a[i]);printf("\n");}}。

相关主题