算法--图的最短路径

最短路径

指定源点的最短路径

算法性质

算法1性质

算法对关联的图的要求:无要求,任意权重图均可。
算法性质:
可求得图G所有s可达节点p,s~p的一条最短路径。

接口设计

template<typename Key, typename Value>
class ShorestPath
{
public:
	class Node;
	typename typedef DataStruct::GraphStruct::Graph<Key, Value> InnerGraph;
	typename typedef DataStruct::Tree::SortedBalanceBinaryTree<Key, Node*> InnerTree;

	class Node
	{
	public:
		double GetDistance()
		{
			return m_nDistance;
		}

		typename InnerGraph::Node* GetGraphNode()
		{
			return m_pGraphNode;
		}

		Node* GetPreNode()
		{
			return m_pPreNode;
		}

	private:
		Node()
		{
			m_nDistance = -1.0;
			m_pGraphNode = nullptr;
			m_pPreNode = nullptr;
		}

		Node(typename InnerGraph::Node* pGraphNode_)
		{
			m_nDistance = -1.0;
			m_pGraphNode = pGraphNode_;
			m_pPreNode = nullptr;
		}

		~Node()
		{
		}

		void Reset()
		{
			m_pPreNode = nullptr;
			m_nDistance = -1.0;
		}

	private:
		double m_nDistance;
		typename InnerGraph::Node* m_pGraphNode;
		Node* m_pPreNode;
		friend class ShorestPath;
	};

	ShorestPath(const InnerGraph& nGraph_);
	~ShorestPath();

	DataStruct::Array::DynArray<Node*> Run(const Key& nSourceKey_);
private:
	const InnerGraph& m_nGraph;
	InnerTree m_nNodeMappingTree;
};

实现

构造

template<typename Key, typename Value>
ShorestPath<Key, Value>::ShorestPath(const InnerGraph& nGraph_)
	: m_nGraph(nGraph_)
{
	DataStruct::Array::DynArray<typename InnerGraph::Node*> _arrGraphNodes = m_nGraph.GetNodesArray();
	for (int _i = 0; _i < _arrGraphNodes.GetSize(); _i++)
	{
		Node* _pNode = nullptr;
		try
		{
			_pNode = new Node(_arrGraphNodes[_i]);
		}
		catch (...)
		{
			_pNode = nullptr;
			throw "out of memory";
		}

		InnerTree::Pair _nPair;
		_nPair.m_nKey = _arrGraphNodes[_i]->GetPair().m_nKey;
		_nPair.m_nValue = _pNode;
		m_nNodeMappingTree.Add(_nPair);
	}
}

析构

template<typename Key, typename Value>
ShorestPath<Key, Value>::~ShorestPath()
{

}

算法1

template<typename Key, typename Value>
DataStruct::Array::DynArray<typename ShorestPath<Key, Value>::Node*> ShorestPath<Key, Value>::Run(const Key& nSourceKey_)
{
	InnerGraph::Node* _pGraphNode = m_nGraph.SearchNode(nSourceKey_);
	if (_pGraphNode == nullptr)
	{
		throw "can not find key in graph";
	}

	DataStruct::Array::DynArray<Node*> _arrpNodes;
	DataStruct::Array::DynArray<InnerTree::Pair>_arrTreePairs = m_nNodeMappingTree.GetArray();
	for (int _i = 0; _i < _arrTreePairs.GetSize(); _i++)
	{
		_arrpNodes.Add(_arrTreePairs[_i].m_nValue);
		_arrpNodes[_i]->Reset();
	}

	DataStruct::Array::DynArray<typename InnerGraph::Node*> _arrGraphNodes = m_nGraph.GetNodesArray();
	DataStruct::Array::DynArray<typename InnerGraph::Edge*> _arrGraphEdges = m_nGraph.GetEdgesArray();
	for (int _i = 0; _i < _arrGraphNodes.GetSize(); _i++)
	{
		for (int _j = 0; _j < _arrGraphEdges.GetSize(); _j++)
		{
			InnerGraph::EdgeIdentity _nIndentity = _arrGraphEdges[_j]->GetIdentity();
			Node* _pNode = nullptr;
			m_nNodeMappingTree.Search(_nIndentity.m_nStartKey, _pNode);
			if (_pNode == nullptr)
			{
				throw "cannot find key in tree";
			}

			if (_pNode->m_pPreNode == nullptr
				&& _pNode->m_pGraphNode != _pGraphNode)
			{
				continue;
			}

			if (_pNode->m_pGraphNode == _pGraphNode)
			{
				_pNode->m_nDistance = 0;
			}

			Node* _pNode2 = nullptr;
			m_nNodeMappingTree.Search(_nIndentity.m_nEndKey, _pNode2);
			if (_pNode2 == nullptr)
			{
				throw "can not find key in tree";
			}

			if ((_pNode2->m_pPreNode == nullptr
				&& _pNode2->m_pGraphNode != _pGraphNode)
				|| (_pNode->m_nDistance + _arrGraphEdges[_j]->m_nWeight) < _pNode2->m_nDistance)
			{
				_pNode2->m_pPreNode = _pNode;
				_pNode2->m_nDistance = _pNode->m_nDistance + _arrGraphEdges[_j]->m_nWeight;
			}
		}
	}

	bool _bSuccess = true;
	for (int _j = 0; _j < _arrGraphEdges.GetSize(); _j++)
	{
		InnerGraph::EdgeIdentity _nIndentity = _arrGraphEdges[_j]->GetIdentity();
		Node* _pNode = nullptr;
		m_nNodeMappingTree.Search(_nIndentity.m_nStartKey, _pNode);
		if (_pNode->m_pPreNode != nullptr
			|| _pNode->m_pGraphNode == _pGraphNode)
		{
			Node* _pNode2 = nullptr;
			m_nNodeMappingTree.Search(_nIndentity.m_nEndKey, _pNode2);
			if ((_pNode2->m_pPreNode == nullptr && _pNode2->m_pGraphNode != _pGraphNode)
				|| (_pNode->m_nDistance + _arrGraphEdges[_j]->m_nWeight) < _pNode2->m_nDistance)
			{
				_bSuccess = false;
				break;
			}
		}
	}

	if (_bSuccess == false)
	{
		throw "shortest path is not exist";
	}
	
	return _arrpNodes;
}

算法目标&算法的性质证明

算法对关联的图的要求:无要求,任意权重图均可。
算法目标:
求图G所有s可达节点p,s~p的一条最短路径。
目标可实现性证明【正确性证明】
算法处理过程:
设图G的节点个数为n,边的个数为m
执行n次循环迭代
每次执行时,对所有边,依次执行边的松弛
正确性证明:
图G如果是无环的,
则,易于知道给定源点s,对于s可达的任一节点p。
s~p,包含s,p在内路径上节点个数<=n。
图G如果是有环的,只要环路权重之和大于0,
则,对于s可达的任一节点p,s~p最短路径,
包含s,p在内路径上节点个数<=n。
图G如果是有环,且环路权重之和小于等于0,
则,对于s可达的任一节点p,s~p最短路径不存在。

综合,
对s的可达节点p,
在s~p最短路径存在的情况下,s~p最短路径上包含s,p下的节点个数<=n

循环不变式:
在执行第k次迭代时,
我们将得到所有最短路径上节点个数为k+1的最短路径信息。
证明:
初始时,
只有s的m_nDistance为0,其余节点皆为无效值。
s~s最短路径节点数为1。循环不变式成立。

第k次循环迭代时,
依据循环不变式,
我们已经得到所有最短路径上节点个数小于等于k的最短路径信息。
对于任意最短路径上节点个数为k+1的最短路径信息。
假设s~q的最短路径中包含节点个数最少的一条最短路径上含k+1个节点。
则,必有s~t->q
必有s~t是一条s~t的最短路径,
且s~t路径上包含k个节点。
由于我们的假设,
我们在本次迭代前已经得到所有最短路径上节点个数为k的最短路径信息。
故,
迭代后,
我们将得到所有剩余节点中,
最短路径上包含k+1个节点的最短路径信息。

得证。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章