【问题标题】:List sort() vs own sort() Time Difference列表排序()与自己的排序()时差
【发布时间】:2013-10-14 15:28:02
【问题描述】:

我对此有疑问;

我有这样的课

class myCLass {
    private:
        string name;
        float value;
    public:
        float getValue();
};

我有超过 1,000,000 个物品,我必须根据物品的价值对这些物品进行排序。所以我创建了那个指针列表;

list<myClass *> objectList;

然后用超过 1.000.000 个对象填充它。现在你可以说向量是最好的方法,如果你的对象小于 30-40 位,那么无论如何我创建它是绝对正确的;

bool ec(myClass *s1, myClass *s2) 
{
    return (s1->getValue() < s2->getValue());
}

然后在主函数中;

time = clock();
objectList.sort(ec);    // Sort with STL.
time = clock() - time;
cout << ((float)time)/CLOCKS_PER_SEC << "\t:time to sort" << endl;

而且只需要 1.2 秒!这对我来说太不可思议了,记住它是最慢的列表容器可能是矢量可以更有效:) 无论如何我的问题是我写了一个插入排序和合并排序算法,如果有人使用我的排序算法,如果他/她想要缩短 100 万个对象需要 3 小时,是的 3 小时 :) 我想知道为什么它比它更多。而且我使用通用算法进行合并和插入,没有什么不同,他们计算出真实的结果。比如我的 insertSort() 就是这样;

void sort::insertionSort(list<myClass *> &normalList, list<myClass *> &sortedList){

    list<myClass*>::iterator sortedIterator;

    sortedList.clear();
    iter = normalList.begin(); // iter describing on constructor
    sortedList.push_back(*iter);
    iter++;

    for(; iter != normalList.end(); iter++){

        sortedIterator = (--sortedList.end());

        while( (*iter)->getValue() < (*sortedIterator)->getValue() && sortedIterator!=(--sortedList.begin() ) ){
        sortedIterator--;
        }
        sortedList.insert(++sortedIterator,*iter);
    }
}

我的插入排序()的基准表;

n=10      => 0      second;
n=100     => 0      second;
n=1.000   => 0      second;
n=10.000  => 0.96   second;
n=20.000  => 4.73   seconds;
n=50.000  => 34.22  seconds;
n=100.000 => 306.62 seconds

我无法控制超过 100.000 :)

这是正常的还是我搞错了?

注意:我尝试使用向量进行插入排序,对于 n=100.000,时间是 50 秒,所以尽管 n=100.000 而不是 1.000.000,但我仍然无法达到 1.29 秒 :)

注2:这是mergeSort()的基准;

n=10      => 0      second;
n=100     => 0      second;
n=1.000   => 0.02      second;
n=10.000  => 0.8   second;
n=20.000  => 3.07   seconds;
n=50.000  => 21.7  seconds;
n=100.000 => 106.73 seconds

【问题讨论】:

  • 经验/知识和编译器内在函数。
  • 是的,插入排序比库中使用的排序方法慢很多,比如合并排序和快速排序。你说你也实现了归并排序,结果如何?另外,你的归并排序是什么样的?
  • 请注意,您的版本也会创建列表的副本...排序不是“到位”。
  • 插入排序的时间复杂度(最坏情况)大约为 O(n²)。
  • 请记住,不同算法的排序时间因原始数据的顺序而异。预排序的数据有一个时序,可能与按相反顺序排序的数据不同。

标签: c++ algorithm stl mergesort


【解决方案1】:

算法理论告诉你,插入排序的复杂度 O(n2) 而快速排序的复杂度 O(n log(n))。对于大型数据集,这是一个很大的差异;粗略地说,您的算法会慢 n / log(n) 倍。

当您考虑对数取对数的影响时,这种差异会变得非常大:如果您对宇宙中的粒子数取以 10 为底的对数,答案大约是 87。

【讨论】:

  • 快速排序的最佳情况复杂度为 O(n lg n)。最坏的情况是 O(n^2)。通常,它离随机数据的最佳情况不远,但确实存在退化情况。
【解决方案2】:

插入排序比内置算法渐进地慢。虽然插入排序的复杂度为O(n^2),但按照标准,内置算法的复杂度为O(n*log(n))。因此,与内置排序算法相比,您拥有的元素越多,您的算法就越慢。

实现自己的排序算法几乎不值得,因为内置实现已经非常优化。

【讨论】:

  • 几乎可以肯定是归并排序,而不是引入排序; introsort 需要随机访问迭代器,而 std::list 只有双向迭代器。
  • 不,当然std::list sort 不是 introsort。我已经删除了这一位,因为它不适用于列表。我没有仔细阅读这个问题。谢谢
  • 我知道复杂性,但我相信虽然它是 O(n^2),但计算它并不需要很长时间。如果有 stl 合并或 stl 插入排序,它不会花费 3 个小时来计算。虽然我做了一个 mergeSort() 并且运行时间仍然超过它。我想知道stl插入排序或合并排序是否可以更快地完成?
  • @user2879337 没有 STL 插入排序。 std::sort 在带有随机访问迭代器的容器上(例如 std::vectorstd::deque)将使用快速排序或介绍排序(通常,尽管它可以合法地使用堆排序); std::list&lt;&gt;::sort 将使用归并排序,直接操作指针,这样就不会创建新节点。
【解决方案3】:

您的版本基本上是将排序列表构造成一个新的 列表。虽然您只是在复制指针,但您仍在做 每个节点的新分配等。估计是会员 函数 sort 从不创建或删除节点;它的运作方式 更改现有节点之间的指针。 (而且当然, 不涉及插入排序;这将是一个纯粹的合并 排序。)

【讨论】:

  • it will be a pure merge sort 内置的 C++ 排序函数不是结合了几种算法吗?即sort不仅使用归并排序算法?
  • @AlexandruBarbarosie 在对列表进行排序时还有哪些有效的算法?
  • 虽然 1.000.000 个元素排序我已经分配了 1.000.000 个指针分配,而且我尝试在同一个列表上排序并且我使用向量但结果没有什么不同: (
  • @JamesKanze 这就是我问的原因。
  • @user2879337 插入排序不是特别有效。
猜你喜欢
  • 2010-10-25
  • 1970-01-01
  • 1970-01-01
  • 2017-07-05
  • 2017-11-06
  • 2016-11-15
  • 1970-01-01
  • 2019-06-14
  • 2011-04-14
相关资源
最近更新 更多