圖的拓撲排序
算法性質
若深度優先後,對p,q兩節點。
設p的結束時間大於q的結束時間。
則,圖中不可能存在q到p的邊。
進一步,
拓撲排序後的節點序列,
前面的節點可能可以到達後面的節點,
但後面的節點不會到達前面的節點。
接口設計
template<typename Key, typename Value>
class TopologySort
{
public:
typename typedef DataStruct::GraphStruct::Graph<Key, Value> InnerGraph;
TopologySort(const InnerGraph& nGraph_);
~TopologySort();
DataStruct::Array::DynArray<typename DepthFirstVisit<Key, Value>::Node*> Run();
private:
TopologySort(const TopologySort& nTopoAl_) = default;
TopologySort& operator=(const TopologySort& nTopoAl_) = default;
private:
typename DepthFirstVisit<Key, Value> m_alDepthFirstVisit;
};
實現
構造
template<typename Key, typename Value>
TopologySort<Key, Value>::TopologySort(const HighLevelStruct::Graph<Key, Value>& nGraph_)
: m_alDepthFirstVisit(nGraph_)
{
}
析構
template<typename Key, typename Value>
TopologySort<Key, Value>::~TopologySort()
{
}
算法運行
template<typename Key, typename Value>
DataStruct::Array::DynArray<typename DepthFirstVisit<Key, Value>::Node*> TopologySort<Key, Value>::Run()
{
DataStruct::Array::DynArray<typename DepthFirstVisit<Key, Value>::Node*> _arrNodes = m_alDepthFirstVisit.Run();
_arrNodes.Sort([](DepthFirstVisit<Key, Value>::Node* pNode1_, DepthFirstVisit<Key, Value>::Node* pNode2_)
{
int _nRet = pNode1_->GetLastVisitTime() - pNode2_->GetLastVisitTime();
if (_nRet > 0)
{
return -1;
}
else if (_nRet < 0)
{
return 1;
}
else
{
return 0;
}
});
return _arrNodes;
}
算法目標&算法的性質證明
證明:
對無環圖運行深度優先搜索算法,
深度優先算法處理後,若節點p的結束時間 > 節點q的結束時間,
則圖中可能存在p到q的邊,不可能存在q到p的邊
結合深度優先算法的性質
我們知道,
若算法處理後,節點p的結束時間 > 節點q的結束時間
則,
要麼 p,q在主循環某個節點t的visit中被訪問
此時,
a.1要麼在訪問鏈p->x1->...->xn->q中被訪問
a.2要麼在
t->x1->...->xk->y1->...->yn->q
t->x1->...->xk->z1->...->zm->p
其中,對xk可達節點按順序執行訪問時,先訪問y1,後z1中被訪問
b.要麼p,q分別在主循環某節點t1,t2的visit中被訪問
且t1在t2之後執行
綜合,a.1,a.2,b三種情況,
此時可以斷定
圖中
可能存在p->q的邊
也可能不存在p->q的邊
現在證明,圖中不存在q->p的邊,已知圖是無環圖。
則,p,q執行深度優先的情況可能是:
a.1.p,q在主循環某個節點p的visit中被訪問,在訪問鏈p->x1->...->xn->q中被訪問
若是這種情況,則p->x1->...->xn->q->p形成環路,與已知矛盾。故不是。
a.2.p,q在主循環某個節點t的visit中被訪問,在
t->x1->...->xk->y1->...->yn->q
t->x1->...->xk->z1->...->zm->p
其中,對xk可達節點按順序執行訪問時,先訪問y1,後z1中被訪問
若存在q->p的邊,則在y1分支訪問q時,對q所有可達且未訪問節點進行訪問時,會訪問p,
這與現實情況相違背。
故不是這種情況。
b.p,q分別在主循環某節點t1,t2的visit中被訪問
且t1在t2之後執行
若存在q->p的邊,
則在t2的visit中對q的所有可達且未被訪問節點進行訪問時,會訪問p
這與現實相違背。
故不是這種情況。
綜合,若假設成立,則在所有可能情況都無法滿足假設。
故,假設不成立。得證。