最短路徑
指定源點的最短路徑
算法性質
算法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個節點的最短路徑信息。
得證。