【问题标题】:Fastest Way To Implement A Queue in Java在 Java 中实现队列的最快方法
【发布时间】:2012-08-27 14:11:54
【问题描述】:

我想知道我应该对此代码进行哪些更改以减少其执行时间。

import java.util.*;

public class ExamPeekableQueueImpl <E extends Comparable<E>> implements ExamPeekableQueue<E> {

    LinkedList<E> li = new LinkedList<E>();

    public ExamPeekableQueueImpl(){
    }

    public void enqueue(E e){
        if(li.isEmpty()){
            li.add(0, e);
        }
        else
        li.add(e);
    }

    public E dequeue(){
        li.pollFirst();
        return null;
    }

    public void printlist(){
        System.out.println(li.toString());
    }

    public E peekMedian(){
        int var = (((li.size())/2)+1);
        Collections.sort(li);
        //Integer var2 = li.get(var);
        System.out.println("the median is:" + li.get(var-1));
        return null;
    }

    public E peekMaximum(){
        Collections.sort(li);
        System.out.println("the maximum is:" + li.getLast());
        return null;
    }

    public E peekMinimum(){
        Collections.sort(li);
        System.out.println("the minimum is:" + li.getFirst());
        return null;
    }

    public int size(){
        li.size();
        return 0;
    }   
}

我还想知道是实现queuesLinkedList 更快还是ArrayList 或任何其他数据结构。

【问题讨论】:

  • 您在哪里需要改进?添加或达到峰值?如果达到峰值,那么为什么不尝试树集呢?还是允许复制?请提供更多信息
  • 或者使用ArrayList而不是LinkedList
  • 每次需要最大值、中值或最小值时对集合进行排序肯定是非常低效的。
  • 最后一个问题是一个非常典型的家庭作业问题。确定这不是家庭作业?您可能需要重新表述问题,以便获得更好的答案。
  • @brimborium:考试与家庭作业/学校作业有何不同?

标签: java queue


【解决方案1】:

这是一个加载的问题。

你想加快什么操作?现在,您的 peekMin/Max/Mid 代码非常慢,因为您必须每次都进行排序。但是,您的插入代码很快。如果你愿意,你可以在内部维护一个排序的数据结构。这会减慢您的插入方法,但会加快您的窥视方法。像这样的操作之间通常需要权衡速度。很少能够仅加速某些数据结构上的所有操作,因此您需要选择您认为常见的操作,并对其进行优化。

这是关于您想要加快哪些操作。

【讨论】:

    【解决方案2】:

    目前您有 O(1) 用于插入,O(nlogn) 用于getMin/getMax/getMedian。您可以使用排序数据结构将 logn 从 getter 移动到插入部分。或者,您可以保留插入,并通过对列表进行线性搜索并仅存储最小值来优化getMin/getMax。对于getMedian,没有什么可做的,因为您需要为此设置一个排序集。

    进一步的优化是存储最小值/最大值并在每个插入步骤期间更新这两个值。这在插入时不会有任何(非常量)变化,并将您的 getMin/getMax 减少到 O(1)。 (感谢泰迪尔

    这同样适用于getMedian,您可以在其中将排序列表与您的链接列表并行保存。然后,您可以简单地从该列表的中间选择中位数。当然,这会将插入时间更改为 O(logn) 或更糟(取决于您使用的列表),并且还会使存储空间量翻倍。所以这是一种比getMin/getMax 更昂贵的优化。

    【讨论】:

      【解决方案3】:

      回答你的后一个问题。请查看this 主题,了解在结构中使用数组或链表的区别。

      另外,作为建议,在声明结构时,请始终使用接口作为类型,这样您就可以在不影响功能的情况下更改实现。

      【讨论】:

        【解决方案4】:

        视情况而定。

        实际上,大多数回答/评论的人没有意识到的一件事是 Collections.sort 在几乎排序的列表上提供了大约 N 性能。 (N log N 是列表未排序时的性能。)

        正如其他人所说,也许您应该在更改列表而不是阅读列表时进行排序。也许您应该使用有序集而不是列表。 (如果您确实需要一个列表来保存一个项目的多个副本,请考虑使用有序映射并将出现次数设为值。)

        您还可以考虑创建一个对象来存储集合并跟踪最小值和最大值而不对其进行排序。如果找到中位数很少,或者如果您不需要中位数,这将很有效。

        【讨论】:

          【解决方案5】:

          在 peekMaximum() 和 peekMinimum() 方法中,可以直接使用 Collections.max(li)Collections.min(li) 方法,而不是对 LinkedList 进行排序。

          我认为这样可以节省排序列表所浪费的时间。

          【讨论】:

            猜你喜欢
            • 2012-12-31
            • 2021-04-20
            • 2023-04-07
            • 2012-06-24
            • 2013-11-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多