【问题标题】:An efficient algorithm to sort millions of words in a DoubleLinkedList一种对 DoubleLinkedList 中数百万个单词进行排序的有效算法
【发布时间】:2012-11-25 16:39:15
【问题描述】:

我正在使用 Java 开发一个简单的搜索引擎。

搜索引擎首先将包含要搜索的文件(txt 文件)的目录名称作为输入,并且在每个文件中包含许多单词。

然后搜索引擎为搜索中遇到的所有单词创建一个倒排索引 目录。引擎读取每个文件并将每个单词插入到 doubleLinkedList 中。

问题是,当我处理包含 100 个 .txt 文件的目录时:

索引时间:~201ms 排序时间:2463ms


排序一个目录包含1000个文件

索引时间:2461ms 排序时间:922654ms


排序一个目录包含10000个文件

大约 10 小时 :(


  1. 有没有什么办法可以减少执行时间?

  2. 我使用了插入排序,对排序算法有什么建议吗?

DoubleLinkedList 类的实现

public class DoubleLinkedList<T> {
    private Node<T> head;
    private Node<T> current;

    public DoubleLinkedList(){
        head = current = null;
    }
    public boolean empty(){
        return head == null;
    }
    public boolean last(){
        return current.next==null;
    }
    public boolean first(){
        return current.previous == null;
    }
    public boolean full(){
        return false;
    }
    public void findFirst(){
        current = head;
    }
    public void findNext(){
        current = current.next;
    }
    public void findPrevious(){
        current = current.previous;
    }
    public T retrieve(){
        return current.data;
    }
    public void update(T val){
        current.data = val;
    }
    public void insert(T val){
        if(head == null){
            head = current = new Node<T>(val);
        }else{
            Node<T> tmp = new Node<T>(val);
            tmp.next = current.next;
            tmp.previous = current;
            if(current.next != null)
                current.next.previous = tmp;
            current.next = tmp;
            current = tmp;
        }
    }
    public void remove(){
        if(current == head){
            head = head.next;
            if(head!=null){
                head.previous=null;
            }
        }else{
            current.previous.next = current.next;
            if(current.next!=null){
                current.next.previous = current.previous;
            }
        }
        if(current.next == null){
            current = head;
        }else{
            current = current.next;
        }
    }


}

【问题讨论】:

  • 将您的排序算法更改为O(n log n) 类似QuickSortO(n) 类似RadixSort
  • 我可以建议对于搜索引擎,依赖任何排序方式都不会很好地扩展吗?
  • @Mohammad:你是什么意思,你用了 insertSort?你没用吗:Collections.sort(doubleLinkedList)?这是归并排序
  • @Cratylus 不,我使用了不同的 DoubleLinkedList。我没有使用任何形式的“收藏”。
  • @Mohammad:这不是标准集合吗?你想出了自己的数据结构?所以基本上你想出了你自己的双链接列表实现,你自己的插入排序实现和 1)你抱怨你有性能问题 2)你没有发布你的代码?

标签: java performance sorting linked-list search-engine


【解决方案1】:

插入排序在(最坏情况)O(n^2) 时间运行。

您可以尝试在 (IIRC) O(nlogn) 时间运行的 Mergesort、QuickSort 或 HeapSort。这会更快。

【讨论】:

  • 至少补充一点,DoubleLinkedList 不是用于排序操作的好数据结构,而不是根据我的评论提供一些答案 =\。
  • @LuiggiMendoza 我在看到您的评论之前写下了我的答案。如果您认为我将您的评论复制到答案中,我很抱歉——我没有这样做。
【解决方案2】:

当然还有更快的方法。其实还有dozens of faster ways :-)

但除非您喜欢重新发明轮子,否则您可以简单地使用Collections.sort(list)。另外,如果性能很重要,我建议使用ArrayList 而不是LinkedList,因为它可以提供更好的引用局部性并占用更少的内存。

对于长度为 10000 的列表,与插入排序相比,这应该将执行时间减少 3 个数量级(即 1000 倍)。

【讨论】:

    【解决方案3】:

    使用ArrayList,然后调用list.trim() 删除空的保留列表空间,然后只需调用Collections.sort(list)LinkedListArrayList 差 99.5%。

    如果还是很慢:接下来只需尝试:
    使用ArrayList,构建String[] words,并使用Arrays.sort( words)进行排序
    。 Collection.sort 使用(修改后的)MergeSort。

    此算法提供有保证的 n log(n) 性能。

    您可以通过避免集合的开销来加快速度,我曾经将 MyArrayListInt 与 Quicksort 一起使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-26
      • 1970-01-01
      • 2011-09-03
      相关资源
      最近更新 更多