Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 给定每个列表中最多包含N个元素的K个排序列表,对所有项返回一个排序迭代器_Java_Algorithm_Data Structures_Min Heap - Fatal编程技术网

Java 给定每个列表中最多包含N个元素的K个排序列表,对所有项返回一个排序迭代器

Java 给定每个列表中最多包含N个元素的K个排序列表,对所有项返回一个排序迭代器,java,algorithm,data-structures,min-heap,Java,Algorithm,Data Structures,Min Heap,我不愿意创建一个“merge”方法来接受k个列表,并本着空间复杂性的精神将列表的内容合并到另一个列表中。这是一个可以使用“最小堆”实现的k路合并问题吗。任何指针都会非常有用 Example: List 1: [1, 4, 5, 8, 9] List 2: [3, 4, 4, 6] List 3: [0, 2, 8] Would yield the following result: Iterator -> [0, 1, 2, 3, 4, 4, 4, 5

我不愿意创建一个“merge”方法来接受k个列表,并本着空间复杂性的精神将列表的内容合并到另一个列表中。这是一个可以使用“最小堆”实现的k路合并问题吗。任何指针都会非常有用

Example: List 1: [1, 4, 5, 8, 9]
     List 2: [3, 4, 4, 6]
     List 3: [0, 2, 8]
    Would yield the following result:

    Iterator -> [0, 1, 2, 3, 4, 4, 4, 5, 6, 8, 8, 9]
公共类CustomListIterator实现迭代器{
私有布尔加迭代器=true;
私有布尔BalanceTreeInteratorFlag=false;
私有E f_元素;
私人E s_元素;
私有迭代器左;
私有迭代器权限;
私人最终比较人;
公共CustomListIterator(比较器比较器){
这个比较器=比较器;
}
公共CustomListIterator(左迭代器、右迭代器、比较器){
this.left=左;
这个。右=右;
这个比较器=比较器;
}
公共无效加法器(迭代器迭代器){
如果(!加拿大人)
抛出新的ConcurrentModificationException();
if(right==null){
右=迭代器;
返回;
}else if(left==null){
左=迭代器;
返回;
}
如果(!balanceTreeIteratorFlag){
右=平衡树Fiterators(迭代器,右);
}否则{
左=平衡树拟合算子(迭代器,左);
}
balanceTreeIteratorFlag=!balanceTreeIteratorFlag;
}
专用迭代器BalanceTreeFiterators(迭代器迭代器_1,迭代器迭代器_2){
if(迭代器\u 2 CustomListIterator的实例){
((CustomListIterator)迭代器_2).加法器(迭代器_1);
}否则{
迭代器_2=新的CustomListIterator(迭代器_1,迭代器_2,比较器);
}
返回迭代器2;
}
公共布尔hasNext(){
if(加扰器){
if(left!=null&&left.hasNext()){
f_元素=left.next();
}
if(right!=null&&right.hasNext()){
s_元素=右。下一步();
}
}
加拿大人=假;
返回f|u元素!=null | s|u元素!=null;
}
公共教育{
E下一步;
if(加扰器){
if(left.hasNext()){
f_元素=left.next();
}
if(right.hasNext()){
s_元素=右。下一步();
}
}
加拿大人=假;
if(s_元素==null&&f_元素==null){
抛出新的NoTouchElementException();
}
if(f_元素==null){
next=s_元素;
s_元素=right.hasNext()?right.next():null;
下一步返回;
}
如果(s_元素==null){
next=f_元素;
f_element=left.hasNext()?left.next():null;
下一步返回;
}
返回findNext();
}
公共空间删除(){
}
私人E findNext(){
E下一步;
if(比较器比较(f_元素,s_元素)<0){
next=f_元素;
f_element=left.hasNext()?left.next():null;
下一步返回;
}
next=s_元素;
s_元素=right.hasNext()?right.next():null;
下一步返回;
}
}


我不认为这是最好的方法(使用树)。关于如何仅通过覆盖next()hasNext()和remove()来实现此功能的任何建议?

合并多个排序列表基本上有三种不同的方法:

  • 连续双向合并
  • 分而治之
  • 基于优先级队列的
  • 在下面的讨论中,
    n
    是指所有列表中项目的总数<代码>k表示列表的数量

    案例1最容易设想,但效率最低。假设你有四个列表,A,B,C和D。使用这个方法,你合并A和B来创建AB。然后你合并AB和C来创建ABC。最后,将ABC与D合并以创建ABCD。该算法的复杂度接近O(n*k)。在A和B上迭代三次,在C上迭代两次,在D上迭代一次

    分而治之的解决方案是合并A和B来创建AB,然后合并C和D来创建CD。然后合并AB和CD以创建ABCD。在最好的情况下,当列表具有相似数量的项目时,这种方法是O(n*log(k))。但是,如果列表的长度变化很大,该算法的运行时间可以接近O(n*k)

    有关这两种算法的更多信息,请参阅我的博客。有关分而治之方法的详细信息,请参见

    基于优先级队列的合并工作如下:

    public class CustomListIterator<E> implements Iterator<E>{
    
    private boolean canAddIterators = true;
    private boolean balanceTreeIteratorFlag = false;
    private E f_element;
    private E s_element;
    private Iterator<E> left;
    private Iterator<E> right;
    private final Comparator<E> comparator;
    
    public CustomListIterator(Comparator<E> comparator){
        this.comparator = comparator;
    }
    
    public CustomListIterator(Iterator<E> left, Iterator<E> right, Comparator<E> comparator){
        this.left = left;
        this.right = right;
        this.comparator = comparator;
    }
    
    public void addIterator(Iterator<E> iterator){
        if (!canAddIterators)
            throw new ConcurrentModificationException();
    
        if (right == null){
            right = iterator;
            return;
        }else if (left == null){
            left = iterator;
            return;
        }
    
        if (!balanceTreeIteratorFlag){
            right = balanceTreeOfIterators(iterator, right);
        }else{
            left = balanceTreeOfIterators(iterator, left);
        }
    
        balanceTreeIteratorFlag = !balanceTreeIteratorFlag;
    }
    
    private Iterator<E> balanceTreeOfIterators(Iterator<E> iterator_1, Iterator<E> iterator_2){
        if (iterator_2 instanceof CustomListIterator){
            ((CustomListIterator<E>)iterator_2).addIterator(iterator_1);
        } else{
            iterator_2 = new CustomListIterator<E>(iterator_1, iterator_2, comparator);
        }
        return iterator_2;
    }
    
    public boolean hasNext() {
        if (canAddIterators){
            if (left != null && left.hasNext()){
                f_element = left.next();
            }
            if (right != null && right.hasNext()){
                s_element = right.next();
            }
        }
        canAddIterators = false;
        return f_element != null || s_element != null;
    }
    
    public E next() {
        E next;
        if (canAddIterators){
            if (left.hasNext()){
                f_element = left.next();
            }
            if (right.hasNext()){
                s_element = right.next();
            }
        }
    
        canAddIterators = false;
    
        if (s_element == null && f_element == null){
            throw new NoSuchElementException();
        }
    
        if (f_element == null){
            next = s_element;
            s_element = right.hasNext() ? right.next() : null;
            return next;
        }
    
        if (s_element == null){
            next = f_element;
            f_element = left.hasNext() ? left.next() : null;
            return next;
        }
    
        return findNext();
    }
    
    public void remove() {
    
    }
    
    private E findNext(){
        E next;
        if (comparator.compare(f_element, s_element) < 0){
            next = f_element;
            f_element = left.hasNext() ? left.next() : null;
            return next;
        }
        next = s_element;
        s_element = right.hasNext() ? right.next() : null;
        return next;
    }
    
    该算法在最坏情况下被证明是O(n*log(k))。您可以看到,每个列表中的每个项目都只添加到优先级队列中一次,从优先级队列中删除一次。但是队列在任何时候都只包含
    k
    项。因此,内存需求非常小

    Java中迭代器的实现使得优先级队列实现稍微不方便,但它很容易通过一些帮助器类修复。最重要的是,我们需要一个迭代器,让我们在不使用它的情况下查看下一项。我将其称为
    peakableiterator
    ,如下所示:

    Create a priority queue to hold the iterator for each list
    while the priority queue is not empty
        Remove the iterator that references the smallest current number
        Output the referenced value
        If not at end of iterator
            Add the iterator back to the queue
    
    这两个类是您为获取和比较单个迭代器的下一项而编写的代码的更正式的实现

    最后,
    MergeIterator
    初始化
    PriorityQueue
    ,以便您可以调用
    hasNext
    next
    方法来迭代合并列表:

    // IteratorComparator lets us compare the next items for two PeekableIterator instances.
    public class IteratorComparator<E> implements Comparator<PeekableIterator<E>> {
        private final Comparator<E> comparator;
    
        public IteratorComparator(Comparator<E> comparator) {
            this.comparator = comparator;
        }
    
        public int compare(PeekableIterator<E> t1, PeekableIterator<E> t2) {
            int rslt = comparator.compare(t1.getCurrent(), t2.getCurrent());
            return rslt;
        }
    }
    
    //合并迭代器合并来自多个排序迭代器的项
    //生成单个排序序列。
    公共类MergeIterator实现了迭代器{
    专用最终迭代器比较器;
    私人最终优先权队列PQUE;
    //使用要合并的数组或序列列表调用
    公共合并迭代器(列表迭代器、比较器){
    this.comparator=新的迭代器比较器(comparator);
    //初始容量设置为11,因为这是默认值,
    //没有一个构造函数可以让我提供一个没有容量的比较器。
    
    // IteratorComparator lets us compare the next items for two PeekableIterator instances.
    public class IteratorComparator<E> implements Comparator<PeekableIterator<E>> {
        private final Comparator<E> comparator;
    
        public IteratorComparator(Comparator<E> comparator) {
            this.comparator = comparator;
        }
    
        public int compare(PeekableIterator<E> t1, PeekableIterator<E> t2) {
            int rslt = comparator.compare(t1.getCurrent(), t2.getCurrent());
            return rslt;
        }
    }
    
    // MergeIterator merges items from multiple sorted iterators
    // to produce a single sorted sequence.
    public class MergeIterator<E> implements Iterator<E> {
        private final IteratorComparator<E> comparator;
        private final PriorityQueue<PeekableIterator<E>> pqueue;
    
        // call with an array or list of sequences to merge
        public MergeIterator(List<Iterator<E>> iterators, Comparator<E> comparator) {
            this.comparator = new IteratorComparator<E>(comparator);
    
            // initial capacity set to 11 because that's the default,
            // and there's no constructor that lets me supply a comparator without the capacity.
            pqueue = new PriorityQueue<PeekableIterator<E>>(11, this.comparator);
    
            // add iterators to the priority queue
            for (Iterator<E> iterator : iterators) {
                // but only if the iterator actually has items
                if (iterator.hasNext())
                {
                    pqueue.offer(new PeekableIterator(iterator));
                }
            }
        }
    
        public boolean hasNext() {
            return pqueue.size() > 0;
        }
    
        public E next() {
            PeekableIterator<E> iterator = pqueue.poll();
            E rslt = iterator.next();
            if (iterator.hasNext()) {
                pqueue.offer(iterator);
            }
            return rslt;
        }
    
        public void remove() {
            // TODO: Throw UnsupportedOperationException
        }
    }
    
    private void DoIt() {
        String[] a1 = new String[] {"apple", "cherry", "grape", "peach", "strawberry"};
        String[] a2 = new String[] {"banana", "fig", "orange"};
        String[] a3 = new String[] {"cherry", "kumquat", "pear", "pineapple"};
    
        // create an ArrayList of iterators that we can pass to the
        // MergeIterator constructor.
        ArrayList<Iterator<String>> iterators = new ArrayList<Iterator<String>> (
                Arrays.asList(
                        Arrays.asList(a1).iterator(),
                        Arrays.asList(a2).iterator(),
                        Arrays.asList(a3).iterator())
        );
    
        // String.CASE_INSENSITIVE_ORDER is a Java 8 way to get
        // a String comparator. If there's a better way to do this,
        // I don't know what it is.
        MergeIterator<String> merger = new MergeIterator(iterators, String.CASE_INSENSITIVE_ORDER);
        while (merger.hasNext())
        {
            String s = merger.next();
            System.out.println(s);
        }
    }