【问题标题】:How do I sort rest of the elements that I insert in a list by keeping the first insertion remain in its position?如何通过保持第一个插入保持在其位置来对插入列表中的其余元素进行排序?
【发布时间】:2020-09-22 08:27:32
【问题描述】:

假设我正在尝试使用包含列表在 CPP 中的列表中插入随机内容,

list <string> newList;
list<string>::iterator z = newList.begin();
//James(Remains static, rest sorted)  -> Abraham-> Brian-> Chuck-> David-> Rick-> Morty
newList.insert(z,James);
newList.insert(z,David);
newList.insert(z, Rick);
newList.insert(z, Abraham);
newList.insert(z, Brian);
newList.insert(z, Morty);
newList.insert(z, Chuck);

如何以及在哪里调用 newList.sort() 以使除第一个插入(即 James)之外的所有它们都排序?

【问题讨论】:

  • 如果您只有 1 个 James,则可以提供很好的答案。如果有多个 James,你想发生什么?

标签: c++ list sorting


【解决方案1】:

这是一个潜在的解决方案,首先删除第一个条目,然后进行排序。

auto front = newList.front();
newList.pop_front();
newList.sort();
newList.push_front(front);

这将使整个列表排序,但开头的任何内容(在您的示例中为James)都将重新添加到列表的前面。

【讨论】:

  • 说front在编译时没有命名类型,可能是什么问题?
  • 我们的解决方案非常相似:您的优势是所需的排序更少。我的优点是第一个元素的迭代器仍然有效,而且类型不需要是可复制的。
  • @nxd 升级你的编译器。
  • @nxd 听起来您的编译器处于旧版 C++03 模式(或者太旧以至于它支持 C++03)。 auto 关键字(在此上下文中)是 C++11。但是你可以很容易地通过写std::string front = newList.front(); 来解决这个问题,事实上,我还是建议这样做,以获得更清晰的代码。类型是你的朋友。
  • 至少std::move 字符串。你这里有两份。非常浪费。
【解决方案2】:

保持第一个元素位置的简单解决方案:

  • 将迭代器存储到第一个元素
  • 对列表进行排序
  • 将存储的迭代器中的元素拼接回开头

如果“第一个插入”不是第一个元素 - 毕竟元素可以插入到任意位置 - 那么需要更复杂的逻辑。

不幸的是,标准库中似乎不存在用于子列表的通用排序算法。

【讨论】:

  • 很遗憾std::list::sort不能接受位置,std::list不能和std::sort一起使用,否则你可以使用迭代器位置来指定子列表。
  • 这是“正确”的解决方案,无论是在性能方面还是在语义方面。您希望拼接节点,而不是不必要地和混乱地复制值。
  • @AsteroidsWithWings 有了 move,Chris 的解决方案基本上没问题,除了迭代器失效。迭代器的稳定性几乎是使用链表的唯一原因。
  • 说到迭代器,我刚刚又看了一遍 OP 的 inserts,我们确定 James 是第一个元素吗?
  • 我想最初的 begin() 是结束迭代器,它仍然是结束迭代器,所以 inserts 是 push_backs。还是它仍然是开始迭代器?呃。
【解决方案3】:

使用自定义比较器,将 James 放在所有其他比较器之前:

bool compare(const std::string& a, const std::string& b) {
    if (a == b) return false;
    else if (a == James) return true;
    else if (b == James) return false;
    else return a < b;
}

您需要注意 a==b 的情况,以实现严格的弱排序(James &lt; James 必须返回 false)。然后James 在所有其他元素之前,所有其他元素在James 之后,否则您只需比较这两个元素。

请注意,如果列表中有多个James,则它们都将被此比较放在前面,因此它并没有完全按照您的要求进行。

【讨论】:

  • 如果James 出现多次怎么办 ;)
  • @ChrisMM 那么两者都会放在前面:(
  • 这对James 很好,在这种情况下恰好是第一次插入。但当Bobby_Tables 是第一次插入时,效果就不太好了。
  • 总是感谢反馈,但无论如何它没有回答问题,没有删除它,因为它可能在某些特殊情况下有用,但并没有真正动机进一步“修复”它
  • 我会写成return std::tie(a == James, a) &lt; std::tie(b == James, b);
【解决方案4】:
 auto first = newList.front();
 newList.sort();
 cout<<first<<" ";
 for(auto it :newList)
    cout<<it<<" ";

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-24
    • 1970-01-01
    • 1970-01-01
    • 2013-02-09
    • 1970-01-01
    • 1970-01-01
    • 2012-11-22
    相关资源
    最近更新 更多