【问题标题】:Performing recursion on a list C++ [duplicate]在列表 C++ 上执行递归 [重复]
【发布时间】:2018-07-11 19:52:17
【问题描述】:

我正在尝试确定我可以使用 std list 从列表中删除的最大项目数以获得最小大小。但是,它一直以错误的内存访问而告终。

这是我的递归函数:

int step (list<int> mylist) {
    int count = mylist.size();
    // Terminations
    if (!checkRemaining(mylist)) {
        return mylist.size();
    }
    if (mylist.empty()) {
        return 0;
    }
    //printf("mysize: %d\n", mylist.size());

    // Else we do not terminate first
    for (auto i=mylist.begin(); i != prev(mylist.end()); ++i)
    {
        if ((*i + *next(i))%2 == 0) // Problem starts from here, bad access
        {
            mylist.erase(next(i));
            mylist.erase(i);
            printf("this size %lu\n", mylist.size());

            list<int> tempList = mylist;
            for (auto it = tempList.begin(); it != tempList.end(); it++) {
                printf("%d ", *it);
            }
            printf("\n");

            int temp = step (tempList);
            if (temp < count) count = temp;
        }
    }

    return count;
}

它设法减小到所需的大小,但由于内存访问错误,程序会崩溃。

【问题讨论】:

  • std::list::erase 成员函数使迭代器无效。这似乎是问题所在。
  • .erase 有替代品吗?
  • @Wilson 否,但它还会返回下一个迭代器 fromw,您应该在擦除后继续该迭代器。
  • 还有一个例子here

标签: c++ recursion linked-list


【解决方案1】:

一旦你做了mylist.erase(i);i 就失效了,所以你在循环中的++i 就是UB。

您的代码应如下所示:

for (auto i = mylist.begin(); i != mylist.end() && i != prev(mylist.end()); /* Empty */)
{
    if ((*i + *next(i)) % 2 == 0)
    {
        mylist.erase(next(i));
        i = mylist.erase(i);
        // maybe you want prev(i) if i != mylist.begin()

#ifdef DEBUG
        std::cout << "this size " << mylist.size() << "\n";
        for (const auto& e : myList) {
            std::cout << e << " ";
        }
        std::cout << "\n";
#endif
        count = std::min(count, step(myList));
    } else {
        ++i;
    }
}

此外,当您删除最后一个元素时,最终检查应正确处理。

【讨论】:

  • @UKMonkey:当你不擦除项目时,你会增加ielse 分支)。当您擦除项目(真正的分支)时,您检索下一个元素(查看i = mylist.erase(i);
  • 是的 - 我错过了你现在在 remaining code 中期待 break 的事实
  • @UKMonkey:我添加了完整的循环内容。我不希望 break (如果最后一个 else 块成为常规块,可能是 continue
  • 感谢工作!
猜你喜欢
  • 1970-01-01
  • 2012-09-10
  • 2017-02-21
  • 2013-08-17
  • 2011-05-09
  • 1970-01-01
  • 2011-07-21
  • 1970-01-01
  • 2017-03-10
相关资源
最近更新 更多