算法--圖的最短路徑

最短路徑

指定源點的最短路徑

算法性質

算法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個節點的最短路徑信息。

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