电子科技大学通信学院网络工程系版的Dijkstra算法
算法伪代码
DijkstraAlg(G(V,E),s)
FOR all vertex j in V DO
d(j) = ∞; p(j) = NULL; //d(j)顶点j到s源点的距离
S= {s}; d(s)=0; p(s)= NULL; //p(j)顶点j的前向点
Update(s);
WHILE S ≠ V DO
i = FindMin(); S = S U {i};
Update(i);
END WHILE
UPdate(i)函数
Update(i)
FOR each edge e incident to i DO
IF e.weight + d(i) < d(e.head)
d(e.head) = e.weight + d(i);
p(e.head) = i;
END IF
END FOR
FindMin函数
Find vertex v in V – S which has minimum d(v);
RETURN v;
现将源代码粘贴如下:
//Common.h
#ifndef _COMMON_H_
#define _COMMON_H_
#include <list>
#include <map>
#include <queue>
#include <utility>
#include <stdio.h>
#include <vector>
#include <string>
#include <fstream>
#include <algorithm>
#include <assert.h>
#include <iomanip>
#include <set>
#include <bitset>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include<sstream>
#include <iostream>
using namespace std;
typedef int Edge_ID;//链路编号
typedef int Vertex_ID;//节点编号
const unsigned int INFUINT=1000000;
#endif
//Vertex.h
#ifndef VERTEX_H
#define VEREX_H
#include "Common.h"
class CVertex
{
public:
Vertex_ID vertexid; //编号
int Distance; //距离
int previousid; //前向节点
CVertex();
CVertex(Vertex_ID);
CVertex(const CVertex&);
~CVertex();
int getDistance() {return Distance;};
void setDistance(int s);
};
#endif
//Vertex.cpp
#include"Vertex.h"
CVertex::CVertex()
{
}
CVertex::CVertex(Vertex_ID node)
{
vertexid=node;
Distance = INFUINT;
previousid = NULL;
}
CVertex::CVertex(const CVertex &vertex)
{
vertexid=vertex.vertexid;
Distance=vertex.Distance;
previousid=vertex.previousid;
}
CVertex::~CVertex()
{
}
void CVertex::setDistance(int s)
{
Distance=s;
}
//Edge.h
#ifndef EDGE_H
#define EDGE_H
#include "Common.h"
class CEdge
{
private:
Edge_ID EdgeId;
Vertex_ID SourceId;
Vertex_ID SinkId;
int edgeWeight;
public:
CEdge();
CEdge(Edge_ID id,Vertex_ID head,Vertex_ID tail,int weight);
CEdge(Vertex_ID head,Vertex_ID tail,int weight);
CEdge(const CEdge&);
~CEdge();
void setEdgeId(Edge_ID id);
void setSourceId(Vertex_ID id);
void setSinkId(Vertex_ID id);
void setWeight(int wei);
Edge_ID getEdgeId() {return EdgeId;};
Vertex_ID getSourceId() {return SourceId;};
Vertex_ID getSinkId() {return SinkId;};
int getedgeWeight() {return edgeWeight;};
};
#endif
//Edge.cpp
#include"Edge.h"
CEdge::CEdge()
{}
CEdge::CEdge(Edge_ID edge,Vertex_ID head,Vertex_ID tail,int weight)
{
EdgeId = edge;
SourceId = head;
SinkId = tail;
edgeWeight = weight;
}
CEdge::CEdge(Vertex_ID head,Vertex_ID tail,int weight)
{
SourceId = head;
SinkId = tail;
edgeWeight = weight;
}
CEdge::CEdge(const CEdge&edge)
{
EdgeId = edge.EdgeId;
SourceId = edge.SourceId;
SinkId = edge.SinkId;
edgeWeight = edge.edgeWeight;
}
CEdge::~CEdge()
{}
void CEdge::setEdgeId(Edge_ID id)
{
EdgeId = id;
}
void CEdge::setSourceId(Vertex_ID id)
{
SourceId = id;
}
void CEdge::setSinkId(Vertex_ID id)
{
SinkId = id;
}
void CEdge::setWeight(int wei)
{
edgeWeight =wei;
}
//Graph.h
#ifndef GRAPH_H
#define GRAPH_H
#include"Common.h"
#include "Vertex.h"
#include "Edge.h"
class CGraph
{
private:
int numVertex, numEdge; //图中节点数、边数
list<CEdge*> IncidentList; // 边集合
map<int, CVertex*> mapVID_Vertex; // <节点编号,节点>
list<CVertex*> listTempMark; // //临时标记的节点集合
map<int, list<CEdge*> > mapVID_listEdge; //点和关联出边信息
map<int,list<CEdge*> > mapVID_RevListEdge;//<节点编号,入邻接边>
void Update(int v);
public:
CGraph(ifstream&);
CGraph(list<CEdge> listEdge);
~CGraph();
bool ReadEdgeInfo(ifstream& inFile);
void InsertEdge(int link_id,int tail,int head,int wei);
void Work(list<CEdge*>& ed_list);//函数Work(参数list<CEdge*>& ed_list )
void Dijkstra(int s);
};
#endif
//Graph.cpp
#include "Graph.h"
//比较指针
bool le(CVertex* c1,CVertex* c2)
{
if (c1->Distance<c2->Distance)
return true;
else return false;
}
CGraph::CGraph(ifstream& infile)
{
if (!ReadEdgeInfo(infile))
{
cerr << "something wrong when read file for edge info!" << endl;
exit(1);
}
}
CGraph::~CGraph()
{
}
void CGraph::InsertEdge(int link_id,int tail,int head ,int wei)
{
CEdge* edge=new CEdge(link_id,tail,head,wei);
IncidentList.push_back(edge);
}
bool CGraph::ReadEdgeInfo(ifstream& inFile)
{
string line,data;
int edge_id,source_id,sink_id;
int weight;
getline(inFile,line);
getline(inFile,line); //第二行
istringstream str_line(line);//赋给str_line istringstream 可以输出到指定的类型
str_line>>data>>numVertex; //str_line 输出到 data numvertex
getline(inFile,line); //第三行 .....
istringstream str_line2(line);
str_line2>>data>>numEdge;
getline(inFile,line);
while(getline(inFile,line))
{
istringstream str_line(line);
str_line>>edge_id>>source_id>>sink_id>>weight;
cout<<edge_id<<" "<<source_id<<" "<<sink_id<<" "<<weight<<endl;
InsertEdge(edge_id,source_id,sink_id ,weight);
}
Work(IncidentList); //存入所有边的信息
return true;
}
void CGraph::Work(list<CEdge*>& ed_list)
{
list<CEdge*>::iterator ed_it;
map<int, list<CEdge*> >::iterator adj_it; //<编号,list<边> >
map<int, CVertex*>::iterator cv_it; //<编号,list<点> >
if(!mapVID_Vertex.empty()) //清空
mapVID_Vertex.clear();
if(!mapVID_listEdge.empty())
mapVID_listEdge.clear();
if(!mapVID_RevListEdge.empty())
mapVID_RevListEdge.clear();
for (ed_it=ed_list.begin();ed_it!=ed_list.end();++ed_it)
{
int head=(*ed_it)->getSourceId();
int tail=(*ed_it)->getSinkId();
CVertex *newhead=new CVertex(head);
CVertex *newtail=new CVertex(tail);
//初始化mapVID_Vertex
mapVID_Vertex.insert(make_pair(head,newhead));//点标号 和点的信息
mapVID_Vertex.insert(make_pair(tail,newtail));
list<CEdge*> *temp=new list<CEdge*>;
mapVID_listEdge.insert(make_pair(head,*temp));
mapVID_listEdge.insert(make_pair(tail,*temp));
list<CEdge*> temp2;
mapVID_RevListEdge.insert(make_pair(head,temp2));
mapVID_RevListEdge.insert(make_pair(tail,temp2));
}
for (ed_it=ed_list.begin();ed_it!=ed_list.end();++ed_it)
{
mapVID_listEdge[(*ed_it)->getSinkId()].push_back(*ed_it);
}
//在mapVID_listRevEdge中加入边
for (ed_it=ed_list.begin();ed_it!=ed_list.end();++ed_it)
{
mapVID_RevListEdge[(*ed_it)->getSourceId()].push_back(*ed_it);
}
}
void CGraph::Dijkstra(int s)
{
map<int, CVertex*>::iterator i,iend;
iend = mapVID_Vertex.end();
for( i=mapVID_Vertex.begin(); i != iend; i++)
{
if ( (i->second)->vertexid == s)
(i->second)->setDistance(0);
else(i->second)->setDistance(INFUINT);
listTempMark.push_back(i->second);
}
Update(s);
while( ! listTempMark.empty() )
{
listTempMark.sort(le); //按照距离排序
int j = (*listTempMark.begin())->vertexid; //取最小的点
cout << "点 " << j << " 前向点 "<<(*listTempMark.begin())->previousid
<<" 距离 "<<(*listTempMark.begin())->Distance <<endl;
listTempMark.pop_front(); //把j删除掉
Update(j);
}
}
void CGraph::Update(int v)
{
list<CEdge*> lEdge = mapVID_listEdge[v]; //点和 出边
list<CEdge*>::iterator i,iend;
iend = lEdge.end();
for( i = lEdge.begin(); i!=iend; i++)
{
int weight = (*i)->getedgeWeight();
CVertex* head = mapVID_Vertex[(*i)->getSourceId()]; //遍历
CVertex* tail = mapVID_Vertex[v]; //一个
if ( tail->Distance + weight < head->Distance )
{ head->Distance = tail->Distance + weight;
head->previousid = v;
}
}
}
//main.cpp
#include"Graph.h"
#include"Common.h"
int main()
{
ifstream edgeinfo;
edgeinfo.open("link.txt");
if (! edgeinfo)
{
cerr<<"Can't open the file!"<<endl;
exit(1);
}
CGraph gra(edgeinfo);
gra.Dijkstra(0);
return 0;
}
// End///
文本内容:
link
vertexnum 6
edgenum 9
id source sink weight
0 1 0 2
1 2 1 4
2 3 2 2
3 3 4 2
4 4 5 3
5 5 0 4
6 5 1 1
7 4 1 2
8 2 4 3