第五周作业——3.Dijkstra算法的实现
2014-04-09 22:51
477 查看
题目原址
因为没实现动态读取文本数据,所以需要注意调整边数.
程序中没实现二分堆的优先队列.使用容器来实现最小键值的获取和调整,因此效率较低.
优先队列往后有空再实现.
文本一题图与结果图:
文本二结果图:
#include <iostream> #include <fstream> #include <iterator> #include <list> using namespace std; #define MAX_EDGE 2550 #define SAFE_DEL(p) { if (p!=NULL) { delete [] p;}} class Vertex_Weight { public: int no; float weight; Vertex_Weight(){} Vertex_Weight(int n,float w) { no=n; weight=w; } bool operator <(Vertex_Weight &t) { if(weight<t.weight) return true; else return false; } bool operator >(Vertex_Weight &t) { if(weight>t.weight) return true; else return false; } }; float *dist=NULL; int *prever=NULL; int ImportToArray(const char *filename,float *array) //将filename内的纯数字文本导入数组array; { int count=0; ifstream fin; fin.open(filename); if( fin.fail() ) { cout<<"file read fail!"<<endl; return -1; } while( fin.eof() ==false ) fin>>array[count++]; fin.close(); return count; } void CreateAdjTable(list<int> *AdjTable,int *array,int count) //创建邻接表 { for(int i=2;i<count;i+=2) { AdjTable[ array[i] ].push_back( array[i+1] ); } } void CreateReverseAdjTable(list<int> *AdjTable,int *array,int count) //创建反图邻接表 { for(int i=2;i<count;i+=2) { AdjTable[ array[i+1] ].push_back( array[i] ); } } void ReverseAdjTable(list<int> *AdjTable,list<int> *RAdjTable,int vertexNum) //根据邻接表创建反图邻接表 { list<int>::iterator it; for(int i=0;i<vertexNum;i++) for(it=AdjTable[i].begin();it!=AdjTable[i].end();++it) { RAdjTable[ *it ].push_back(i); } } void ShowAdjTable(list<int> *AdjTable,int vertexNum) //显示邻接表 { for(int i=0;i<vertexNum;i++) { cout<<i<<":"; copy(AdjTable[i].begin(),AdjTable[i].end(), ostream_iterator<int>(cout," ")); cout<<endl; } } void CreateWeightAdjTable(list<Vertex_Weight> *WAdjTable,float *array,int count) //创建带权的邻接表 { for(int i=2;i<count;i+=3) { Vertex_Weight t; t.no=array[i+1]; t.weight=array[i+2]; WAdjTable[ (int)array[i] ].push_back(t); } } void ShowWeightAdjTable() { } void GraphBFS(list<Vertex_Weight> *WAdjTable,int start,int vertexNum) //广度优先遍历 { float unlimit=INT_MAX/2; for(int i=0;i<vertexNum;i++) dist[i]=unlimit; //算是无穷 dist[start]=0; list<int> Q; Q.push_back(start); while( !Q.empty() ) //队列Q不为空时 { int u=Q.front(); Q.pop_front(); //获取队列头元素,并删除该元素 list<Vertex_Weight>::iterator it; for(it=WAdjTable[u].begin();it!=WAdjTable[u].end();++it) { if ( unlimit==dist[it->no]) //v=it->no; { Q.push_back(it->no); dist[it->no]=dist[u]+1; } } } } void decreasekey(list<Vertex_Weight> &H,int v) { list<Vertex_Weight>::iterator it; for(it=H.begin();it!=H.end();it++) { if(v==it->no) { it->weight=dist[v]; //更新键值 break; } } } int deletemin(list<Vertex_Weight> &H) //有误 { list<Vertex_Weight>::iterator it=H.begin(); list<Vertex_Weight>::iterator delp=it; int u=it->no; int d=it->weight; for(;it!=H.end();it++) { if( it->weight < d ) { u=it->no; d=it->weight; delp=it; } } H.erase(delp); //移除dist值最小的元素 return u; } void Dijkstra(list<Vertex_Weight> *WAdjTable,int start,int vertexNum) { float unlimit=INT_MAX/2; for(int i=0;i<vertexNum;i++) { dist[i]=unlimit; prever[i]=-1; } dist[start]=0; //////////////////////////////////// 创建伪优先队列 list<Vertex_Weight> H(vertexNum,Vertex_Weight(0,0)); //最小键值总在队列头 list<Vertex_Weight>::iterator it; int i=start; for(it=H.begin();it!=H.end();++it) { it->no=i; it->weight=dist[i]; i=(i+1)%vertexNum; } ///////////////////////////////////// while(!H.empty()) { int u=H.front().no; //获取最小键值的顶点号 H.pop_front(); //获取后删除该元素 //int u=deletemin(H); //同上 for(it=WAdjTable[u].begin();it!=WAdjTable[u].end();++it) //此时v==it->no { if(dist[it->no] > dist[u] + it->weight) //即if dist[v]>dist[u]+l(u,v); { dist[it->no]=dist[u] + it->weight; prever[it->no]=u; decreasekey(H,it->no); } } H.sort(); //排序,使最小键值元素在最前; } } void ShowPath(int start,int vertexNum) { list<int> stack; for(int i=(start+1)%vertexNum;i!=start;i=(i+1)%vertexNum) { int v=i; stack.push_front(v); while(v!=start) { v=prever[v]; stack.push_front(v); } cout<<start<<"到"<<i<<"的路径:"<<endl; copy(stack.begin(),stack.end(),ostream_iterator<int>(cout,"->")); cout<<"路径距离:"<<dist[i]<<endl; stack.clear(); } } void Showdist(int vertexNum) { for(int i=0;i<vertexNum;i++) cout<<i<<"\t"; cout<<endl; for(int i=0;i<vertexNum;i++) cout<<dist[i]<<"\t"; cout<<endl; } void main() { float *array=new float[MAX_EDGE*3]; int count=ImportToArray("tinyEWD.txt",array);//注意文本最后有无空行 int vertexNum=array[0],edgeNum=array[1]; list<Vertex_Weight> *WAdjTable=new list<Vertex_Weight>[vertexNum]; dist=new float[vertexNum]; prever=new int[vertexNum]; CreateWeightAdjTable(WAdjTable,array,count); cout<<vertexNum<<" "<<edgeNum<<endl; cout<<WAdjTable[vertexNum-1].front().no<<" "<<WAdjTable[vertexNum-1].front().weight<<endl; // GraphBFS(WAdjTable,0,vertexNum); Dijkstra(WAdjTable,0,vertexNum); Showdist(vertexNum); ShowPath(0,vertexNum); /* list<int> *AdjTable=new list<int>[vertexNum]; list<int> *RAdjTable=new list<int>[vertexNum]; CreateAdjTable(AdjTable,array,count-1); //创建邻接表 ReverseAdjTable(AdjTable,RAdjTable,vertexNum); //创建反图邻接表 cout<<"邻接表:"<<endl; ShowAdjTable(AdjTable,vertexNum); cout<<"反图邻接表:"<<endl; ShowAdjTable(RAdjTable,vertexNum); ////////////// //销毁动态数组 for(int i=0;i<vertexNum;i++) { AdjTable[i].clear(); RAdjTable[i].clear(); } SAFE_DEL(RAdjTable); SAFE_DEL(AdjTable);*/ //销毁动态数组 for(int i=0;i<vertexNum;i++) { WAdjTable[i].clear(); } SAFE_DEL(dist); SAFE_DEL(WAdjTable); SAFE_DEL(array); }
因为没实现动态读取文本数据,所以需要注意调整边数.
程序中没实现二分堆的优先队列.使用容器来实现最小键值的获取和调整,因此效率较低.
优先队列往后有空再实现.
文本一题图与结果图:
文本二结果图:
相关文章推荐
- 第五周作业——Dijkstra算法的实现
- 第五周作业——Dijkstra算法的实现
- 第五周作业——Dijkstra算法的实现
- 第五周作业——有向图强连通分量的编程实现
- 第五周作业——有向图强连通分量的编程实现
- try,catch(异常作业)用string实现
- 图论:最短路径搜索--Dijkstra算法(c代码实现)
- 第五周作业
- 数值作业:二分法求方程的根之C语言实现代码
- 第五周作业
- //--《面向对象程序设计与VC++实现》作业
- C++实现Dijkstra算法
- 第五周作业
- JSP作业3 - 使用JSP实现简单的用户登录注册页面
- 第五周作业——有向图邻接表表示及反向图构造
- 最短路径Dijkstra算法实现和Floyd算法实现
- [IMWeb训练营作业]vue实现自定义select下拉框组件
- Dijkstra算法的java实现
- 试解释操作系统原理中的作业,进程,线程,管程各自的定义。进程间的通信如何实现?
- 数据结构课程设计---用Dijkstra算法实现一个简易的最佳方案选择