首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用长的公共前缀更快地进行字符串排序?

使用长的公共前缀更快地进行字符串排序?
EN

Stack Overflow用户
提问于 2013-04-27 06:08:46
回答 6查看 989关注 0票数 9

我有一组字符串。其中90%是以"http://www."开头的URL。我想按字母顺序对它们进行排序。

目前我使用的是C++ std::sort()。但是std::sort是基于比较的快速排序的变体,并且比较两个带有长公共前缀的字符串是不有效的。但是(我认为)基数排序也不起作用,因为大多数字符串都放在同一个存储桶中,因为有很长的公共前缀。

对于这个问题,有没有比普通的快速排序/基数排序更好的算法呢?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2013-04-28 07:08:01

最后,我发现一个三元快速排序工作得很好。我在www.larsson.dogma.net/qsufsort.c找到了这个算法。

下面是我修改后的实现,具有类似于std::sort的接口。在我的机器和数据集上,它比std::sort快大约40%。

代码语言:javascript
运行
复制
#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;
}
票数 2
EN

Stack Overflow用户

发布于 2013-04-27 07:09:59

我怀疑,当考虑到URL的平均长度时,您尝试利用每个URL 10个字符级别的公共前缀所花费的处理时间甚至不值得。

只需尝试一个完全标准的排序。如果这还不够快,可以看看并行化或分发一个完全标准的排序。这是一种简单有效的方法。

票数 4
EN

Stack Overflow用户

发布于 2013-04-27 06:12:36

常见的前缀似乎自然而然地暗示了trie数据结构可能很有用。因此,我们的想法是构建所有单词的trie,然后对每个节点进行排序。排序应该是特定节点的子节点驻留在列表中并进行排序。这很容易做到,因为在特定的节点上,我们只需要对子节点进行排序,所以递归解决方案自然会显示出来。看看这个可以获得更多灵感:http://goanna.cs.rmit.edu.au/~jz/fulltext/acsc03sz.pdf

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16245946

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档