Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;:映射、查找周期、算法_C++_Algorithm_Cycle_Stdmap - Fatal编程技术网

C++ C++;:映射、查找周期、算法

C++ C++;:映射、查找周期、算法,c++,algorithm,cycle,stdmap,C++,Algorithm,Cycle,Stdmap,假设以下数据结构: std::map <int, std::vector<int> > M, 如何从段{}中查找所有循环(类似的开始和结束顶点) 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} 以及如何在低时间复杂度的情况下避免重复的片段序列(map可能包含数十万个序列)。任何循环都可以包含n个段{},其中n>=1 初始化阶段:

假设以下数据结构:

std::map <int, std::vector<int> > M, 
如何从段{}中查找所有循环(类似的开始和结束顶点)

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} 
以及如何在低时间复杂度的情况下避免重复的片段序列(map可能包含数十万个序列)。任何循环都可以包含n个段{},其中n>=1

初始化阶段:

std::map M;
M[1]=std::vector{1,8,12,7};
M[4]=std::vector{4,3,5};
M[7]=std::vector{7,9,13,18,0,2};
M[2]=std::vector{2,11,1};
M[5]=std::vector{5,17,10,4};
M[9]=std::vector{9,6,19,14};
M[14]=std::vector{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);
}
std::向量R;
对于(自动im=M.begin();im!=M.end();)
{
向量r,ri=im->秒;
对于(;;)
{
r、 插入(r.end(),ri.begin(),ri.end());
ri=M[r.back()];
im=M.erase(M.find(im->first));
如果(r.back()==r.front())中断;
}
R.推回(R);
}
不幸的是,重复删除代表了一个昂贵的操作。。。我希望有一个更漂亮、更有效的解决方案:-)

谢谢你的帮助…

我的第一次尝试:

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';
}
for(自动it:M)
{
if(it.first首先,您的内部循环需要是一个函数(如果路径不循环怎么办?)

然后,如果

  • 结束节点在数值上小于开始节点(可能是一个循环,但不是规范节点,因此我们不会打印此移位版本)
  • 在路径主表中找不到结束节点
这就引出了一个解决方案:

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;
        }
    }
}
bool try\u follow(int from,std::vector&result)
{
int电流=从;
while(true){
自动路径=M.find(当前);
if(path==M.end())返回false;
当前=路径->第二个.back();
如果(电流<来自)返回false;
插入(result.end(),path->second.begin()+1,path->second.end());
if(current==from)返回true;
}
}
内部主(空)
{
用于(自动和kvp:M)
{
std::向量x;
如果(尝试跟随(kvp.first,x)){

std::循环是否必须包括整个路径,或者是否可以使用任何连接的子序列?请注意,避免重复循环就像给每个循环指定一个规范名称一样简单。要求打印循环以编号最低的节点开始是一个好选择。@Ben Voigt:只有{}内的整个路径本·沃格特:谢谢,这是一个多么好的解决方案!
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';
}
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;
        }
    }
}