算法导论第二十四章-单源最短路径-Cpp代码实现

实现了Bellman-Ford算法和Dijkstra算法。这里的Dijkstra采用了贪心策略。

single_source_min_path.h

#pragma once

/*************************************************
Author:董小歪
Date:2016-06-23
Description:算法导论第二十四章-单源最短路径-Cpp代码实现
**************************************************/

#ifndef SINGLE_SOURCE_MIN_PATH_H
#define SINGLE_SOURCE_MIN_PATH_H

#include <iostream>
#include <vector>
#include <unordered_map>
#include <string>
#include <algorithm>

using namespace std;

struct Graph_Node
{
	int id;			//编号
	int distance;	//距离源点的距离
	Graph_Node* pi;	//前驱
	Graph_Node(int _id):id(_id), pi(nullptr), distance(INT_MAX) {  }
};

class Single_Source
{
public:
	typedef vector<Graph_Node*> G_V;
	typedef vector<pair<Graph_Node*, Graph_Node*>> G_E;
	typedef vector<vector<int>> G_W;
	Single_Source(G_V _V, G_E _E, G_W _w) :V(_V), E(_E), weight(_w) {}
	bool bellman_ford(Graph_Node* s);				//Bellman-Ford算法
	void dijkstra(Graph_Node* s);					//dijkstra算法
	void show_path();
private:
	void initialize_single_source(Graph_Node* s);	//初始化点
	void relax(Graph_Node* u, Graph_Node* v);		//松弛操作
	vector<Graph_Node*> get_adj(Graph_Node* u);		//返回邻接点
	G_V V;		//图的点集合
	G_E E;		//图的边集合
	G_W weight;	//边的权重
};

#endif // !SINGLE_SOURCE_MIN_PATH_H


single_source_min_path.cpp

#include "single_source_min_path.h"

void Single_Source::initialize_single_source(Graph_Node* s)
{
	for (int i = 0; i < V.size(); ++i)
	{
		V[i]->distance = INT_MAX;
		V[i]->pi = nullptr;
		if (V[i] == s)
			V[i]->distance = 0;
	}
}

void Single_Source::relax(Graph_Node* u, Graph_Node* v)
{
	if (u->distance != INT_MAX)
	{
		int w = weight[u->id][v->id];
		if (v->distance == INT_MAX || v->distance > u->distance + w)
		{
			v->distance = u->distance + w;
			v->pi = u;
		}
	}
}

bool Single_Source::bellman_ford(Graph_Node* s)
{
	initialize_single_source(s);
	for (int i = 1; i < V.size(); ++i)
	{
		for (int j = 0; j < E.size(); ++j)
		{
			relax(E[j].first, E[j].second);
		}
	}
	for (int j = 0; j < E.size(); ++j)
	{
		Graph_Node* u = E[j].first;
		Graph_Node* v = E[j].second;
		int w = weight[u->id][v->id];
		if (u->distance != INT_MAX)
		{
			if (v->distance == INT_MAX || v->distance > u->distance + w)
				return false;
		}
	}
	return true;	
}

void Single_Source::dijkstra(Graph_Node* s)
{
	initialize_single_source(s);
	G_V Q = V;
	while (!Q.empty())
	{
		sort(Q.begin(), Q.end(), [](Graph_Node* v1, Graph_Node* v2) { return v1->distance < v2->distance; });
		vector<Graph_Node*> vs = get_adj(Q[0]);
		for (int i = 0; i < vs.size(); ++i)
			relax(Q[0], vs[i]);
		Q.erase(Q.begin());
	}
}

vector<Graph_Node*> Single_Source::get_adj(Graph_Node* u)
{
	vector<Graph_Node*> res;
	for (int i = 0; i < E.size(); ++i)
	{
		if (E[i].first == u)
			res.push_back(E[i].second);
	}
	return res;
}

void Single_Source::show_path()
{
	for (int i = 0; i < V.size(); ++i)
	{
		cout << "顶点" << V[i]->id << "距离源点的最短距离:" << V[i]->distance << "\t";
		cout << "路径是:";
		Graph_Node* temp = V[i];
		string path = to_string(V[i]->id);
		while (temp->pi)
		{
			temp = temp->pi;
			path = to_string(temp->id) + "->" + path;
		}
		cout << path << endl;
	}
}


测试代码:

#include "single_source_min_path.h"

int main()
{
	Graph_Node* node0 = new Graph_Node(0);
	Graph_Node* node1 = new Graph_Node(1);
	Graph_Node* node2 = new Graph_Node(2);
	Graph_Node* node3 = new Graph_Node(3);
	Graph_Node* node4 = new Graph_Node(4);
	vector<Graph_Node*> V = { node0, node1, node2, node3, node4 };
	vector<pair<Graph_Node*, Graph_Node*>> E;
	vector<vector<int>> weight(5, vector<int>(5));
	E.push_back(make_pair(node0, node1)); weight[0][1] = 6;
	E.push_back(make_pair(node0, node3)); weight[0][3] = 7;
	E.push_back(make_pair(node1, node2)); weight[1][2] = 5;
	E.push_back(make_pair(node1, node3)); weight[1][3] = 8;
	E.push_back(make_pair(node1, node4)); weight[1][4] = -4;
	E.push_back(make_pair(node2, node1)); weight[2][1] = -2;
	E.push_back(make_pair(node3, node2)); weight[3][2] = -3;
	E.push_back(make_pair(node3, node4)); weight[3][4] = 9;
	E.push_back(make_pair(node4, node0)); weight[4][0] = 2;
	E.push_back(make_pair(node4, node2)); weight[4][2] = 7;

	Single_Source ss(V, E, weight);
	ss.bellman_ford(node0);
	cout << "Bellman-Ford算法计算的结果:" << endl; ss.show_path();

	Graph_Node* node10 = new Graph_Node(0);
	Graph_Node* node11 = new Graph_Node(1);
	Graph_Node* node12 = new Graph_Node(2);
	Graph_Node* node13 = new Graph_Node(3);
	Graph_Node* node14 = new Graph_Node(4);
	vector<Graph_Node*> V2 = { node10, node11, node12, node13, node14 };
	vector<pair<Graph_Node*, Graph_Node*>> E2;
	vector<vector<int>> weight2(5, vector<int>(5));
	E2.push_back(make_pair(node10, node11)); weight2[0][1] = 10;
	E2.push_back(make_pair(node10, node13)); weight2[0][3] = 5;
	E2.push_back(make_pair(node11, node12)); weight2[1][2] = 1;
	E2.push_back(make_pair(node11, node13)); weight2[1][3] = 2;
	E2.push_back(make_pair(node12, node14)); weight2[2][4] = 4;
	E2.push_back(make_pair(node13, node11)); weight2[3][1] = 3;
	E2.push_back(make_pair(node13, node12)); weight2[3][2] = 9;
	E2.push_back(make_pair(node13, node14)); weight2[3][4] = 2;
	E2.push_back(make_pair(node14, node10)); weight2[4][0] = 7;
	E2.push_back(make_pair(node14, node12)); weight2[4][2] = 6;
	Single_Source ss2(V2, E2, weight2);
	ss2.dijkstra(node10);
	cout << endl << "Dijkstra算法计算的结果:" << endl; ss2.show_path();

	system("pause");
}

测试结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值