我有一组字符串。其中90%是以"http://www."
开头的URL。我想按字母顺序对它们进行排序。
目前我使用的是C++ std::sort()。但是std::sort是基于比较的快速排序的变体,并且比较两个带有长公共前缀的字符串是不有效的。但是(我认为)基数排序也不起作用,因为大多数字符串都放在同一个存储桶中,因为有很长的公共前缀。
对于这个问题,有没有比普通的快速排序/基数排序更好的算法呢?
发布于 2013-04-28 07:08:01
最后,我发现一个三元快速排序工作得很好。我在www.larsson.dogma.net/qsufsort.c找到了这个算法。
下面是我修改后的实现,具有类似于std::sort的接口。在我的机器和数据集上,它比std::sort快大约40%。
#include <iterator>
template<class RandIt> static inline void multiway_qsort(RandIt beg, RandIt end, size_t depth = 0, size_t step_len = 6) {
if(beg + 1 >= end) {
return;
}
struct { /* implement bounded comparing */
inline int operator() (
const typename std::iterator_traits<RandIt>::value_type& a,
const typename std::iterator_traits<RandIt>::value_type& b, size_t depth, size_t step_len) {
for(size_t i = 0; i < step_len; i++) {
if(a[depth + i] == b[depth + i] && a[depth + i] == 0) return 0;
if(a[depth + i] < b[depth + i]) return +1;
if(a[depth + i] > b[depth + i]) return -1;
}
return 0;
}
} bounded_cmp;
RandIt i = beg;
RandIt j = beg + std::distance(beg, end) / 2;
RandIt k = end - 1;
typename std::iterator_traits<RandIt>::value_type key = ( /* median of l,m,r */
bounded_cmp(*i, *j, depth, step_len) > 0 ?
(bounded_cmp(*i, *k, depth, step_len) > 0 ? (bounded_cmp(*j, *k, depth, step_len) > 0 ? *j : *k) : *i) :
(bounded_cmp(*i, *k, depth, step_len) < 0 ? (bounded_cmp(*j, *k, depth, step_len) < 0 ? *j : *k) : *i));
/* 3-way partition */
for(j = i; j <= k; ++j) {
switch(bounded_cmp(*j, key, depth, step_len)) {
case +1: std::iter_swap(i, j); ++i; break;
case -1: std::iter_swap(k, j); --k; --j; break;
}
}
++k;
if(beg + 1 < i) multiway_qsort(beg, i, depth, step_len); /* recursively sort [x > pivot] subset */
if(end + 1 > k) multiway_qsort(k, end, depth, step_len); /* recursively sort [x < pivot] subset */
/* recursively sort [x == pivot] subset with higher depth */
if(i < k && (*i)[depth] != 0) {
multiway_qsort(i, k, depth + step_len, step_len);
}
return;
}
发布于 2013-04-27 07:09:59
我怀疑,当考虑到URL的平均长度时,您尝试利用每个URL 10个字符级别的公共前缀所花费的处理时间甚至不值得。
只需尝试一个完全标准的排序。如果这还不够快,可以看看并行化或分发一个完全标准的排序。这是一种简单有效的方法。
发布于 2013-04-27 06:12:36
常见的前缀似乎自然而然地暗示了trie数据结构可能很有用。因此,我们的想法是构建所有单词的trie,然后对每个节点进行排序。排序应该是特定节点的子节点驻留在列表中并进行排序。这很容易做到,因为在特定的节点上,我们只需要对子节点进行排序,所以递归解决方案自然会显示出来。看看这个可以获得更多灵感:http://goanna.cs.rmit.edu.au/~jz/fulltext/acsc03sz.pdf
https://stackoverflow.com/questions/16245946
复制相似问题