【问题标题】:addLast method for a deque with only one sentinel node只有一个哨兵节点的双端队列的 addLast 方法
【发布时间】:2018-12-10 14:05:44
【问题描述】:

这个问题来自伯克利的数据结构免费在线课程(CS61B)链接可以在这里找到:https://joshhug.gitbooks.io/hug61b/content/chap2/chap23.html

实现链表,使其是循环的,前后指针共享同一个哨兵节点。添加和删​​除操作不得涉及任何循环或递归。单个此类操作必须花费“恒定时间”,即执行时间不应取决于双端队列的大小。

[分配任务的方框和指针图] [1]:https://i.stack.imgur.com/pUgk3.png

例如,如果我的列表是 {1,2,3},那么 sentinel.next.next.item 是 3,而 sentinel.next.next.next.item 是 1

 public class DLList<T> {

        private class Node {
            public T item;
            public Node next;
            public Node prev;

            public Node(T item, Node next, Node prev) {
                this.item = item;
                this.next = next;
                this.prev = prev;
            }

            @Override
            public String toString() {
                return item.toString();
            }
        }

        public Node sentinel ;
        private int size;

        public DLList() {
            this.sentinel = null;
            this.size = 0;
        }

        public void addLast(T item) {
            sentinel.next = new Node(item, null, sentinel);
            sentinel = sentinel.next;  // updatedSentinel
            size++;
        }
    }

我想问一下,如何确保 updatedSentinel.next 一直链接回第一个节点?另外,我的构造函数对于这个类的目的是否正确?当大小为 0 和大小 >= 1 时,实现是否应该不同?

【问题讨论】:

    标签: java data-structures linked-list deque


    【解决方案1】:

    让sentinel指向最后一个节点:如果列表为空则为null,否则sentinel.next为第一个节点(因为列表是循环的)。您不需要任何反向链接。 所以 addLast 将是:

        public void addLast(T item) {
            if (sentinel == null) {
                sentinel = new Node(item, null);
                sentinel.next = sentinel;
            } else {
                sentinel.next = new Node(item, sentinel.nex);
                sentinel = sentinel.next;  // updatedSentinel
            }
            size++;
        }
    

    ¨ 更新:两个链接:

        public void addLast(T item) {
            if (sentinel == null) {
                sentinel = new Node(item, null, null);
                sentinel.next = sentinel;
                sentinel.prev = sentinet;
            } else {
                Node next = sentinel.next;
                sentinel.next = next.prev = new Node(item, next, sentinel);
                sentinel = sentinel.next;
            }
            size++;
        }
    

    【讨论】:

    • 我的 Node 类有三个字段。对于 sentinel.next = new Node(item, sentinel.next);这不起作用。
    【解决方案2】:

    首先,你要检查链表是否为空。如果为空,则将prev,next和sentinel链接到当前节点。

    if(head == null)
    {
      Node a = new Node(item,a,a);
      sentinel.next = a; 
    }
    

    否则找到最后一个节点并将其下一个节点分配给第一个节点。类似地,将前一个节点分配给最后一个节点。您可以跟踪哨兵的下一个节点作为头节点。

    Node head = sentinel.next;
    Node last = head;
    while(last.next != head)
    {
       last = last.next;
    }
    
    Node a = new Node(item,head,last);
    head.prev = a;
    last.next = a;
    

    我认为您的构造函数类没有任何错误。

    【讨论】:

    • 对不起,我应该澄清一下。此处列出了该任务的其他规范: 添加和删除操作不得涉及任何循环或递归。单个此类操作必须花费“恒定时间”,即执行时间不应取决于双端队列的大小。我认为,在你的情况下,如果双端队列的大小很大,你将不得不保持循环很长时间直到你到达终点。
    猜你喜欢
    • 2011-02-14
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    • 2021-10-11
    • 2017-11-25
    • 2021-07-24
    • 2022-01-05
    • 2019-09-09
    相关资源
    最近更新 更多