插入项目或将它们添加到sorting列表后sorting列表是否更快?

如果我有一个sorting列表(比如sorting快速sorting),如果我有很多值要添加,最好是暂停sorting,并将其添加到最后,然后sorting,或使用二进制印章正确放置项目join他们。 如果项目是随机的,或者已经或多或less地有所不同,它会有所作为吗?

如果添加的项目足够从头开始有效地构build列表,则应该可以通过对列表进行sorting来获得更好的性能。

如果项目大多是按顺序的,你可以调整增量更新和常规sorting,以利用这一点,但坦率地说,它通常是不值得的麻烦。 (你也需要小心,比如确保一些意外的sorting不能让你的algorithm花费更长的时间

增量更新和常规列表sorting都是O(N log N),但是你可以得到一个更好的常数因子,然后sorting(我在这里假设你有一些辅助的数据结构,所以你的增量更新可以比O更快地访问列表项(N)…)。 一般来说,一次sorting比增加sorting有更多的devise自由度,因为增量更新必须始终保持完整的顺序,但是一次性批量sorting不会。

如果没有别的,请记住,有很多高度优化的批量sorting可用。

通常使用堆会好得多。 简而言之,它分摊了推动者和select者之间维持秩序的成本。 两个操作都是O(log n),而不是O(n log n),就像大多数其他解决scheme一样。

如果您正在添加一束,您可以使用合并sorting。 对要添加的项目列表进行sorting,然后从两个列表中进行复制,比较项目以确定下一个将被复制的项目。 如果调整目标数组的大小,并从最后开始工作,甚至可以在原地进行复制。

这个解决scheme的效率是O(n + m)+ O(m log m),其中n是原始列表的大小,m是被插入的项目的数量。

编辑:由于这个答案没有得到任何的爱,我想我会充实一些C + +示例代码。 我假设sorting后的列表保存在链表中而不是数组中。 这改变了algorithm,看起来更像插入而不是合并,但原理是相同的。

// Note that itemstoadd is modified as a side effect of this function template<typename T> void AddToSortedList(std::list<T> & sortedlist, std::vector<T> & itemstoadd) { std::sort(itemstoadd.begin(), itemstoadd.end()); std::list<T>::iterator listposition = sortedlist.begin(); std::vector<T>::iterator nextnewitem = itemstoadd.begin(); while ((listposition != sortedlist.end()) || (nextnewitem != itemstoadd.end())) { if ((listposition == sortedlist.end()) || (*nextnewitem < *listposition)) sortedlist.insert(listposition, *nextnewitem++); else ++listposition; } } 

原则上,创build树比sorting列表要快。 对于每个插入,树插入为O(log(n)),从而导致整体O(n log(n))。 sorting在O(n日志(n))。

这就是为什么Java有TreeMap(除了TreeSet,TreeList,List的LinkedList实现之外)。

  • TreeSet保持对象的比较顺序。 关键是由Comparable接口定义的。

  • LinkedList保持插入顺序。

  • 一个ArrayList使用更多的内存,更快的一些操作。

  • 类似地,TreeMap消除了按键sorting的需要。 地图在插入过程中按键顺序构build,并始终按sorting顺序进行维护。

但是,由于某种原因,TreeSet的Java实现比使用ArrayList和sorting要慢很多。

[很难推测为什么它会显着变慢,但是事实如此。 数据应该稍微快一点。 这种事情往往是内存pipe理algorithm分析的代价。]

我会说,让我们testing它! 🙂

我试着用quicksort,但用quicksortsorting几乎sorting的数组是…好吧,不是一个好主意。 我试了一个修改过的,切断了7个元素,并使用插入sorting。 可怕的performance。 我切换到合并sorting。 它可能需要相当多的内存进行sorting(它不是就地),但sorting数组的性能要好得多,在随机数上几乎相同(两者的初始sorting几乎相同,快速sorting只稍快)。

这已经显示了一件事:你的问题的答案强烈依赖于你使用的sortingalgorithm。 如果它在几乎sorting的列表中performance不佳,那么在正确的位置插入会比在最后添加然后重新sorting快得多; 而合并sorting可能不适合你,因为如果列表很大,它可能需要太多的外部内存。 顺便说一句,我使用了一个自定义的合并sorting实现,只使用外部存储的一半天真的实现(这需要尽可能多的外部存储数组大小本身)。

如果合并sorting是没有选项,快速sorting是没有select,最好的select可能是堆sorting。

我的结果是:在最后添加新元素,然后重新sorting数组要比将数组插入正确的位置快几个数量级。 不过,我最初的数组有10万个元素(sorting),我正在添加另一个mio(未sorting)。 所以,如果你添加10个元素到一个10兆数组,正确插入比重新sorting的东西要快得多。 所以你的问题的答案也取决于初始(sorting)数组有多大以及你想添加多less新元素。

如果列表a)已经sorting,并且b)本质上是dynamic的,那么插入sorting列表应该总是更快(find正确的地方(O(n))并且插入(O(1)))。

然而,如果列表是静态的,那么列表的其余部分必须发生(O(n)find正确的地方,O(n)将事物向下滑动)。

无论哪种方式,插入一个sorting列表(或类似二进制search树)应该更快。

O(n)+ O(n)应该总是比O(N log n)快。

这是一样的。 将一个项目插入到一个sorting列表中是O(log N),并且为列表中的每个元素N(从而构build列表)做这个操作将是O(N log N),它是快速sorting的速度(或合并sorting这更接近这种方法)。

如果你将它们插入到前面,那么将会是O(1),但是在之后做一个快速sorting,它仍然是O(N log N)。

我会采取第一种方法,因为它有可能会稍微快一点。 如果列表的初始大小N大于要插入的元素的数量X,则插入方法是O(X log N)。 插入到列表头后的sorting是O(N log N)。 如果N = 0(IE:你的列表最初是空的),以sorting顺序插入的速度或者之后sorting的速度是相同的。

你应该添加它们,然后使用基数sorting,这应该是最佳的

http://en.wikipedia.org/wiki/Radix_sort#Efficiency

如果这是.NET和项目是整数,那么将它们添加到字典是更快(或者如果您在.Net 3.0或更高版本使用HashSet,如果你不介意丢失重复)这给你自动sorting。

我认为string也会以同样的方式工作。 美是你得到O(1)插入和sorting这种方式。

(如果你正在谈论的列表就像C# List<T> 。将正确位置的一些值添加到具有许多值的sorting列表中将需要较less的操作。 但是,如果增加的值的数量变大,则需要更多。

我会build议使用不是一个列表,但在你的情况下一些更合适的数据结构。 例如像二叉树。 一个sorting的数据结构,插入时间最短。

将项目插入sorting列表需要O(n)时间,而不是O(log n)时间。 你必须find放置它的地方,需要O(log n)时间。 但是,你必须改变所有的元素 – 采取O(n)时间。 所以在保持sorting的同时插入是O(n ^ 2) ,其中插入它们然后sorting为O(n log n)

根据您的sorting实现,如果插入的数量远小于列表大小,则可以比O(n log n)更好。 但是,如果是这样的话,这两种方式都没有关系。

如果插入的数量很大,那么插入所有sorting解决scheme,否则可能无所谓。

在高层次上,这是一个非常简单的问题,因为您可以将sorting视为迭代search。 如果要将元素插入到有序数组,列表或树中,则必须search要插入的点。 然后你把它放进去,希望成本低。 所以你可以把一个sortingalgorithm看成是一堆东西,然后逐个search适当的位置并插入它们。 因此,插入sorting(O(n * n))是迭代线性search(O(n))。 树,堆,合并,基数和快速sorting(O(n * log(n)))可以被认为是迭代二分search(O(log(n)))。 如果底层search是O(1),就像在一个有序的哈希表中一样,可以进行O(n)sorting。 (举个例子,把52张卡片扔到52个垃圾箱里。)

所以,对于你的问题的答案是,一次一个地插入一些东西,而不是把它们存起来,然后把它们sorting,应该没有太大的区别。 你当然可以有不变的因素来处理,而那些可能是重要的。

当然,如果n很小,如10,整个讨论就是愚蠢的。

插入一个项目到sorting列表中是O(log n),而sorting列表是O(n log N)这意味着总是先sorting然后插入

但是记住大的'O'只关心速度与项目数量的缩放,可能是因为你的应用程序中间的插入是昂贵的(例如,如果它是一个向量),所以追加和sorting可能会更好。