一种有效的算法,用于对DoubleLinkedList中的数百万个单词进行排序

时间:2012-11-25 16:39:15

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

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

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

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

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

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


对目录进行排序包含1000个文件

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


对目录进行排序包含10000个文件

大约10小时:(


  1. 有没有办法缩短执行时间?

  2. 我使用了插入排序,所以有关排序算法的任何建议吗?

  3. 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;
            }
        }
    
    
    }
    

3 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:1)

当然有更快的方法。事实上,有dozens of faster ways: - )

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

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

答案 2 :(得分:0)

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

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

  

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

你可以通过避免集合的开销来加快速度,我已经使用带有Quicksort的MyArrayListInt完成了这一点。