【问题标题】:Sort after inserting an item into a Linked List?将项目插入链接列表后排序?
【发布时间】:2011-10-02 10:55:46
【问题描述】:

我有一个 C++ 程序可以将节点插入到链表中。节点由一个我们称为 data 的字符串和一个指向下一个节点的指针组成,我们将其称为 next。此外,头节点将被定义为head

我不确定什么更有效 - 1. 将一堆字符串插入我的列表,然后对其进行排序 2. 或者在我插入时对列表进行排序。

我认为是后者,我想知道我将如何实施类似的东西。

我想知道实现这种功能的最简单方法。

【问题讨论】:

    标签: c++ sorting linked-list


    【解决方案1】:

    第一个解决方案:插入 k 个未排序的元素,只需将它们插入到开头,每个都是 O(1)。还有一种:O(nlogn) 在这 k 个元素之后。你得到amortized 的时间是O(nlogn+k)/k = O(n(logn/k))

    第二种解决方案:将元素插入到列表中的排序顺序是O(n),因为您需要在列表中找到该位置。对于 k 次插入,它将是 O(n*k),并摊销 O(n*k/k) = O(n)

    所以第一个解决方案更适合logn < k,第二个解决方案更适合logn > k

    为了提高效率,您可能需要一个排序的数据结构来访问 O(logn) 中的元素,例如 skip-list [它基本上是链表的变体,带有更容易访问的附加信息] 或 avl tree

    【讨论】:

    • 对不起,不明白链表上的排序是如何O(n log n) ?
    • @TonyTheLion: 将其转换为数组 [O(n)] 排序 [O(nlogn)] 从此数组创建列表 [O(n)]
    • 也可以直接在链表上使用快速排序。
    【解决方案2】:

    我回答了一个类似的问题(99% 类似:)) HERE

    现在我猜它是整数,对于字符串,您可以使用 C 库提供的 std::string compare 函数或 strcmp 进行比较

    根据我的意见并查看其他答案,您的应用程序(如果它需要排序的链表)在插入时对数据进行排序会更好。

    【讨论】:

    • 我无法使用您的方法。有一行你只有 temp -> data;这应该是 temp->data=data; 吗?无论哪种方式,我都无法让它正常工作。我会试着找出我做错了什么,然后带着结果回到这里。谢谢:D
    • @chickeneaterguy :html标签一定有问题。即使在 1 年后,我在 html 中编写 ">" 时也遇到问题 :)
    • 谢谢。我使用了不同的方法,但你的方法最有帮助。
    【解决方案3】:

    我认为它实际上并没有影响你如何做,当你在插入时排序时,插入时你会有 O(n),因为你可能需要遍历整个列表才能找到正确的插入点。

    但是,当您在将所有项目添加到列表后进行排序时,您还将有至少 O(n) 的时间在列表中移动项目。

    【讨论】:

      【解决方案4】:

      最简单的解决方案是使用 C++ 已经提供的 - std::liststd::list::sort

      #include <list>
      #include <algorithm>
      #include <iostream>
      #include <string>
      
      class Node {
      public:
          Node(const std::string& data) : Data(data) {
          }
          std::string Data;
      };
      
      bool NodeLess(const Node& n1, const Node& n2) {
          return n1.Data < n2.Data;
      }
      
      void main() {
      
          std::list<Node> l;
          l.push_back(Node("d"));
          l.push_back(Node("c"));
          l.push_back(Node("a"));
          l.push_back(Node("b"));
      
          l.sort(NodeLess);
      
          for (auto i = l.begin(); i != l.end(); ++i)
              std::cout << i->Data.c_str() << " ";
      
      }
      

      如果您可以摆脱它(内存方面),您还可以使用std::vector 对项目进行预排序(通过std::sort),然后再将它们插入到链表中,这可能会更快一些。

      您也可以使用std::map(甚至std::set)代替列表 - 它会在您插入项目时“自动排序”。

      如果你仍然想使用自己的列表,你可以在其中实现beginend,并使用std::stable_sort。请注意,std::stable_sort 需要双向迭代器(不像 std::sort 需要随机访问迭代器)。要在您的列表中实现双向迭代器,您需要将其设为双链接,而不仅仅是单链接。

      如果你想自己实现排序,可以在链表上同时实现QuicksortMergesort

      【讨论】:

      • 如果您打算使用std::list,那么您可能应该考虑使用list::sort 成员函数。当然,配置文件以查看您的应用程序中哪个更好。
      • @Blastfurnace 我完全忘记了std::list::sort,谢谢你提醒我!相应地编辑了答案。
      猜你喜欢
      • 2011-12-22
      • 2013-11-28
      • 1970-01-01
      • 1970-01-01
      • 2011-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多