《算法设计》实习报告班级 XXXX 名 XX 学号 XXXXXXX1.给出Dijkstra算法的思想,并用C或C++实现,并分析该算法的复杂度。
对下图所示的有向网,试利用Dijkstra算法求出从源点1到其他顶点的最短路径。
实习报告的内容:<一>解决问题和算法思想这个问题即为单源最短路问题。
解决单源最短路径的基本思想是把图中所有结点分为两组,每一个结点对应一个距离值。
设置两个结点的集合S和T,集合S中存放已找到最短路径的结点,集合T存放当前还未找到最短路径的结点。
初始状态时,集合S只包含源点,设为V0,然后不断从集合T中选择到源点V0路径长度最短的结点u加入到集合S中,集合S每加入一个新的结点u都要修改从源点V0到集合T中剩余结点的当前最短路径长度值,集合T中各结点的新的当前路径最短路径,为原来的最短路径与从源点过结点u到达该结点的路径长度中的较小者。
此过程不断重复,直到集合T中的结点全部加入到集合S中为止。
<二>调试通过的源程序(1)顺序表打包文件:seqlist.htypedef struct{ datatype list[maxsize];int size;}seqlist;void listinitiate(seqlist *l){ l->size=0;}int listlength(seqlist l){ return l.size;}int listinsert(seqlist *l,int i,datatype x){ int j;if(l->size>=maxsize){ printf("it is too full!\n");return 0;}else if(i<0||i>l->size){ printf("error!\n");return 0;}else{ for(j=l->size;j>i;j--)l->list[j]=l->list[j-1];l->list[i]=x;l->size++;return 1;}}int listdelete(seqlist *l,int i,datatype *x) { int j;if(l->size<=0){ printf("it is empty!\n");return 0;}else if(i<0||i>l->size-1){ printf("error!\n");return 0;}else{ *x=l->list[i];for(j=i+1;j<=l->size-1;j++)l->list[j-1]=l->list[j];l->size--;return 1;}}int listget(seqlist l,int i,datatype *x) { if(i<0||i>=l.size-1){ printf("error!\n");return 0;}else{ *x=l.list[i];return 1;}}(2)邻接矩阵打包文件:adjmgraph.h#include"seqlist.h"typedef struct{seqlist vertices;int edge[maxvertices][maxvertices];int numofedges;}adjmgraph;void initiate(adjmgraph *g,int n){int i,j;for(i=0;i<n;i++)for(j=0;j<n;j++){if(i==j) g->edge[i][j]=0;else g->edge[i][j]=maxweight;}g->numofedges=0;listinitiate(&g->vertices);}void insertvertex(adjmgraph *g,datatype vertex){listinsert(&g->vertices,g->vertices.size,vertex);}void insertedge(adjmgraph *g,int v1,int v2,int weight){if(v1<0||v1>g->vertices.size||v2<0||v2>g->vertices.size) {printf("error!\n"); return;}g->edge[v1][v2]=weight;g->numofedges++;}int getfirstvex(adjmgraph g,int v){int col;if(v<0||v>g.vertices.size){printf("error!\n");exit(1);}for(col=0;col<g.vertices.size;col++)if(g.edge[v][col]>0&&g.edge[v][col]<maxweight)return col;return -1;int getnextvex(adjmgraph g,int v1,int v2){int col;if( v1<0||v1>g.vertices.size||v2<0||v2>g.vertices.size){printf("error!\n");exit(1);}for(col=v2+1;col<g.vertices.size;col++)if(g.edge[v1][col]>0&&g.edge[v1][col]<maxweight)return col;return -1;}(3)图的创建函数打包文件:adjmgraphcreate.h()typedef struct{int row;int col;int weight;}rowcolweight;void creatgraph(adjmgraph *g,datatype v[],int n,rowcolweight E[],int e) {int i,k;initiate(g,n);for(i=0;i<n;i++)insertvertex(g,v[i]);for(k=0;k<e;k++)insertedge(g,E[k].row,E[k].col,E[k].weight);}(4)狄克斯特拉打包文件:dijkstra.h()void dijkstra(adjmgraph g,int v0,int distance[],int path[]){int n=g.vertices.size;int *s=(int *)malloc(sizeof(int)*n);int mindis,i,j,u;for(i=0;i<n;i++){distance[i]=g.edge[v0][i];s[i]=0;if(i!=v0 && distance[i]<maxweight) path[i]=v0;else path[i]=-1;s[v0]=1;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;for(j=0;j<n;j++)if(s[j]==0&&g.edge[u][j]<maxweight&&distance[u]+g.edge[u][j]<dist ance[j]){distance[j]=distance[u]+g.edge[u][j];path[j]=u;}}}(5)主程序:#include<stdio.h>#include<stdlib.h>#include<malloc.h>typedef char datatype;#define maxsize 100#define maxvertices 10#define maxweight 10000#include"adjmgraph.h"#include"adjmgraphcreate.h"#include"dijkstra.h"void main(void){adjmgraph g;char a[]={'1','2','3','4','5','6'};rowcolweightrcw[]={{0,1,20},{0,2,15},{1,0,2},{1,4,10},{1,5,30},{2,1,4},{2,5,10 },{4,3,15},{5,3,4},{5,4,10}};int i, n=6,e=10;int distance[6],path[6];creatgraph(&g,a,n,rcw,e);dijkstra(g,0,distance,path);printf("从节点%c到其他结点的最短距离为:\n",g.vertices.list[0]);for(i=0;i<n;i++)printf("到结点%c的最短距离为%d\n",g.vertices.list[i],distance[i]);}<三>程序运行结果:<四>算法的时间复杂度分析:Dijkstra 算法,算法解决的是有向图中单个源点到其他顶点的最短路径问题。
Dijkstra算法的时间效率依赖于用来实现优先队列的数据结构以及用来表示输入图本身的数据结构,如果图用权重矩阵表示,优先队列用无序数组来实现,该题我们用邻接矩阵来完成,用的就是权重矩阵,所以,该算法属于O(|n|*|n|),时间复杂度为O(n^2)2.依据贪婪法求解问题的思想,编写一个求解下列问题的算法。
设某币种有面额为25分、10分、5分、1分的四种硬币,1元钱等于100分。