单源最短路径Dijkstra算法

Dijkstra算法中设置了一顶点集合S,从源点s到集合中的顶点的最终最短路径的权值均已确定。算法反复选择具有最短

路径估计的顶点u∈V - S,并将u加入S中,对u的所有出边进行松弛,在下列算法实现中,用到了顶点的最小优先队列

Q,排序关键字为顶点的d值。d为实时权值。



代码如下:

#include<iostream>
#include<list>
using namespace std;

#define MAXVALUE 10000			//定义一个最长路径 

//此处Dijkstra算法的图为有向图

struct Edge
{
	int verno;			//邻接数组中节点编号
	int weight;			//权值
	Edge* next;			//指向下一条边
};

struct Vertex
{
	Edge *adj;			//所指向的节点所在边
	int verno;			//邻接数组中节点编号
	char key;			//关键字
};

struct Graph
{
	Vertex *vertexs;	//节点数组
	int vertexnum;		//节点个数
	int adjnum;			//边数
};

class MSWDijkstra
{
public:
	MSWDijkstra(char *vertex,int vernum,char adj[][2],int *weight,int adjnum);
	void DijkstraInsert(int source,int dest,int weight);
	int DijkstraFindKey(char key);
	int DijkstraExtraMin(bool *visited,int length);
	void DijkstraInitSingleSource();
	void DijkstraMSW(char sourceKey);
	void DijkstraOutput();
private:
	int *shortway;
	int *parent;
	Graph *dijkstraGraph;
};

MSWDijkstra::MSWDijkstra(char *vertex,int vernum,char adj[][2],int *weight,int adjnum)
{
	int i,source,dest;

	shortway = new int[vernum];
	parent = new int[vernum];
	dijkstraGraph = new Graph;

	dijkstraGraph->vertexs = new Vertex[vernum];
	dijkstraGraph->adjnum = adjnum;
	dijkstraGraph->vertexnum = vernum;
	for(i = 0;i < vernum;i++)
	{
		dijkstraGraph->vertexs[i].key = vertex[i];
		dijkstraGraph->vertexs[i].verno = i;
		dijkstraGraph->vertexs[i].adj = NULL;
	}

	for(i = 0;i < adjnum;i++)
	{
		source = DijkstraFindKey(adj[i][0]);
		dest = DijkstraFindKey(adj[i][1]);
		DijkstraInsert(source,dest,weight[i]);
		//DijkstraInsert(dest,source,weight[i]);			//无向图与有向图的区别在此
	}
}

void MSWDijkstra::DijkstraInsert(int source,int dest,int weight)
{
	if(dijkstraGraph->vertexs[source].adj == NULL || dijkstraGraph->vertexs[source].adj->weight > weight)
	{
		Edge* newnode = new Edge;
		newnode->verno = dest;
		newnode->weight = weight;
		newnode->next = dijkstraGraph->vertexs[source].adj;
		dijkstraGraph->vertexs[source].adj = newnode;
	}
	else
	{
		Edge* temp = dijkstraGraph->vertexs[source].adj;
		while(temp->next != NULL)						//插入新边的时候,把权值从低到高进行排序
		{
			if(temp->next->weight > weight)
				break;
			temp = temp->next;
		}
		Edge* newnode = new Edge;
		newnode->verno = dest;
		newnode->weight = weight;
		newnode->next = temp->next;
		temp->next = newnode;
	}
}

int MSWDijkstra::DijkstraFindKey(char key)
{
	int i;
	for(i = 0;i < dijkstraGraph->vertexnum;i++)
	{
		if(dijkstraGraph->vertexs[i].key == key)
			break;
	}
	return i;
}

int MSWDijkstra::DijkstraExtraMin(bool *visited,int length)
{
	int min = MAXVALUE;
	for(int i = 0;i < length; i++)
	{
		if(!visited[i])
		{
			if(min != MAXVALUE && shortway[i] < shortway[min] || min == MAXVALUE)
				min = i;
		}
	}
	return min;
}

void MSWDijkstra::DijkstraInitSingleSource()
{
	int vernum = dijkstraGraph->vertexnum;
	for(int i = 0;i < vernum;i++)
	{
		shortway[i] = MAXVALUE;
		parent[i] = i;
	}
}

void MSWDijkstra::DijkstraMSW(char sourceKey)
{
	int i;
	int count = 1;
	Edge* sourceEdge;
	int vernum = dijkstraGraph->vertexnum;
	int source = DijkstraFindKey(sourceKey);
	bool *visited = new bool[vernum];
	for(i = 0;i < vernum;i++)
	{
		visited[i] = false;
	}
	DijkstraInitSingleSource();
	shortway[source] = 0;
	while(count <= vernum)
	{
		i = DijkstraExtraMin(visited,vernum);
		visited[i] = true;
		count++;
		sourceEdge = dijkstraGraph->vertexs[i].adj;
		while(sourceEdge != NULL)
		{
			if((shortway[i] + sourceEdge->weight) < shortway[sourceEdge->verno])
			{
				parent[sourceEdge->verno] = i;
				shortway[sourceEdge->verno] = shortway[i] + sourceEdge->weight;
			}
			sourceEdge = sourceEdge->next;
		}
	}
	delete []visited;
}

void MSWDijkstra::DijkstraOutput()
{
	int i,j,weight;
	list<int> route;
	cout<<"All the most shortest route from source : "<<endl;
	for(i = 0;i < dijkstraGraph->vertexnum;i++)
	{
		j = i;
		weight = shortway[j];
		do
		{
			route.push_front(j);
			j = parent[j];

		}while(parent[j] != j);

		cout<<dijkstraGraph->vertexs[j].key;
		cout<<"---"<<dijkstraGraph->vertexs[route.front()].key;
		route.pop_front();
		while(!route.empty())
		{
			if(route.front() != j)
				cout<<"---"<<dijkstraGraph->vertexs[route.front()].key;
			route.pop_front();
		}
		cout<<"    "<<weight<<endl;
	}

}

int main()
{
	char vertex[] = {'S','T','X','Y','Z'};
	int vernum = 5;
	char adj[][2] = {{'S','T'},{'S','Y'},{'T','X'},{'T','Y'},{'X','Z'},{'Y','T'},{'Y','X'},{'Y','Z'},{'Z','S'},{'Z','X'}};
	int weight[] = {10,5,1,2,4,3,9,2,7,6};
	int adjnum = 10;
	MSWDijkstra *dijkstra = new MSWDijkstra(vertex,vernum,adj,weight,adjnum);
	dijkstra->DijkstraMSW('S');
	dijkstra->DijkstraOutput();

	return 0;
}
结果如下:

All the most shortest route from source :
S---S    0
S---Y---T    8
S---Y---T---X    9
S---Y    5
S---Y---Z    7
请按任意键继续. . .



  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值