【问题标题】:about linear time and constant time of queue implementation on java linked list关于java链表上队列实现的线性时间和常数时间
【发布时间】:2017-01-03 04:41:33
【问题描述】:

如果我维护the least added item 的引用但不维护most recently added 项目的引用,那么我将拥有恒定时间"dequeue" 和线性时间"enqueue"。所以这是我在java链表中实现队列的程序。我想问一下这个程序是否同时维护最少添加的项目和最近添加的项目?所以当我"dequeue""enqueue" 时,这都是恒定的时间?谢谢!

补充:我有点同意第一个答案所说的,所以我尝试了调试模式,它表明 oldlast 在最后一次更改后没有更新,所以它仍然有效......但是从我从 uni 学到的参考理论,就像他说的那样,它不应该工作..任何人都可以告诉我为什么它没有自动更新?(我的java版本1.8)

package tst;

public class linkedlsqueue {

    private class Node {
        String item;
        Node next;
    }

    Node first, last;

    public boolean isEmpty() {
        return first == null;
    }

    public void enqueue(String item) {
        Node oldlast = last;
        last = new Node();
        last.item = item;
        if (isEmpty()) {
            first = last;
        }
        else {
            oldlast.next = last;
        }
    }

    public String dequeue() {
        String item = first.item;
        first = first.next;
        if (isEmpty()) {
            last = null;
        }
        return item;
    }



}

【问题讨论】:

    标签: java algorithm queue


    【解决方案1】:

    是的,你是对的。在这两种情况下都是恒定的。

    最好记录 firstlast 的链接列表。
    有人称它为headtail

    如果您只维护lastfirst 中的一个,则必须通过迭代firstlast 来搜索另一个,反之亦然 - 一个一个元素,即 O(n )。

    就像你在黑暗中一样。
    你手握着一根绳子的末端,你想知道它会通向哪里。
    除了追踪那根绳子,我想不出其他方法。跟踪需要 O(n)。

    我更喜欢使用数组[]。
    使用数组,就像您拥有一张地图、一个太阳和一个超级门户(随机访问)。
    但是,它不在问题的范围内。

    【讨论】:

    • 只是一点:在列表中,尾部就是头部后面的所有内容
    • @Daniel 不同意。快速搜索后:studytonight.com/data-structures/queue-data-structure
    • hmm...当我第一次学习haskell时,我曾经对这样的列表进行递归:对头部做一些事情并将递归调用到尾部(这是列表的其余部分)。我曾经也将最后一个元素称为尾部,但后来我认为这是错误的......也许我应该同时接受:)
    • @Daniel Prolog 也有你所说的定义(tail=列表的其余部分)。我只是意识到它的含义是特定于范围的。
    【解决方案2】:

    想法是正确的,但实现是错误

    看看这个:

    public void enqueue(String item) {
        Node oldlast = last;
        last = new Node();
        last.item = item;
        if (isEmpty()) {
            first = last;
        }
        else {
            oldlast.next = last;
        }
    }
    

    当您执行oldlast = last 时,您不要复制last,您只需将last 引用传递给oldlast

    在整个过程中,oldlast 将是 last 的任何内容。同时,当您执行last = new Node() 时,RESET last 的值。

    如果你只是想入队,正确的方法可以这样工作:

    public void enqueue(String item) {
        Node newNode = new Node();
        newNode.item = item;
        if(isEmpty()){
            first = newNode; last = newNode;
            return;
        }
        this.last.next = newNode;
        this.last = newNode;
    }
    

    要正确复制元素,您应该这样做:

    Node oldlast = new Node();
    oldlast.item = String(last.item);
    

    希望有帮助。

    【讨论】:

    • 我有点同意你说的,所以我尝试了调试模式,它表明 oldlast 在最后一次更改后没有更新,所以它仍然工作......但是从我学到的参考理论uni,就像你说的,它不应该工作......你也可以在编译器上试试......
    • 奇怪...也许编译器将旧节点留在内存中并在其他地方创建新节点
    • 现在想通了,他认为oldlast是last的引用,但当时last也是null的引用,所以oldlast只是null的引用,是别名最后的。只有在 C++ 中,“指向指针的指针”才能这样工作。
    猜你喜欢
    • 2012-06-24
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    • 2015-05-02
    • 2018-01-22
    • 2014-08-22
    • 1970-01-01
    相关资源
    最近更新 更多