[英]C++: std::map, find cycles, algorithm
假設以下數據結構:
std::map <int, std::vector<int> > M,
其中val由圖形的頂點序列表示,鍵為序列的第一個頂點。 例如
{1} {1, 8, 12, 7}
{4} {4, 3, 5}
{7} {7, 9, 13, 18, 0, 2}
{2} {2, 11, 1}
{5} {5, 17, 10, 4}
{9} {9, 6, 19, 14}
{14} {14, 15, 9}
如何從段{}中查找所有循環(相似的起始和結束頂點)
C1: {1 8 12 7} {7 9 13 18 0 2} {2 11 1}
C2: {4 3 5} {5 17 10 4}
C3: {9 6 19 14} {14, 15, 9}
以及如何避免重復的片段序列,且時間復雜度低(地圖可能包含成千上萬個序列)。 任何循環都可以包含n個段{},其中n> = 1。
初始化階段:
std::map <int, std::vector <int> > M;
M[1] = std::vector<int>{ 1, 8, 12, 7 };
M[4] = std::vector<int>{ 4, 3, 5 };
M[7] = std::vector<int>{ 7, 9, 13, 18, 0, 2 };
M[2] = std::vector<int>{ 2, 11, 1 };
M[5] = std::vector<int>{ 5, 17, 10, 4 };
M[9] = std::vector<int>{ 9, 6, 19, 14 };
M[14] = std::vector<int>{ 14, 15, 9 };
該算法的草案 :
std::vector<std::vector <int> > R;
for (auto im = M.begin(); im != M.end();)
{
std::vector<int> r, ri = im->second;
for(;;)
{
r.insert(r.end(), ri.begin(), ri.end());
ri = M[r.back()];
im = M.erase(M.find(im->first));
if (r.back() == r.front()) break;
}
R.push_back(r);
}
不幸的是,重復刪除代表昂貴的操作...我希望有一個更漂亮,更有效的解決方案:-)
謝謝你的幫助...
首先,您的內部循環必須是一個函數(如果路徑不循環該怎么辦?)
然后,聲明失敗
這導致了一個解決方案:
bool try_follow(int from, std::vector<int>& result)
{
int current = from;
while (true) {
auto path = M.find(current);
if (path == M.end()) return false;
current = path->second.back();
if (current < from) return false;
result.insert(result.end(), path->second.begin()+1, path->second.end());
if (current == from) return true;
}
}
int main(void)
{
for( auto& kvp : M )
{
std::vector<int> x;
if (try_follow(kvp.first, x)) {
std::cout << kvp.first;
for( int y : x )
std::cout << " - " << y;
std::cout << std::endl;
}
}
}
我的第一個裂縫:
for (auto it : M)
{
if (it.first < it.second.back() && it.second.front() == M[it.second.back()].back())
std::cout << "Cycle between " << it.first << " and " << it.second.back() << '\n';
}
當然,不會找到涉及3條以上路徑的循環。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.