连接队列

时间:2017-12-24 06:44:27

标签: java oop

我在Sedgewick和Wayne的算法中遇到了这个问题。

Catenable队列,堆栈或steques。添加一个额外的操作连接(破坏性地)连接两个队列,堆栈或steques(参见练习1.3.32)。提示:使用循环链表,保持指向最后一项的指针。

队列的类定义如下所示。

public class Queue<Item> implements Iterable<Item> {
    private Node<Item> first;    // beginning of queue
    private Node<Item> last;     // end of queue
    private int n;               // number of elements on queue

    // helper linked list class
    private static class Node<Item> {
        private Item item;
        private Node<Item> next;
    }
    // methods to add and remove etc.
}

问题是如何实现实例方法,或者我是否应该实现实例方法,是否应该破坏性地更新两个队列?如果我尝试编写像public void catenate(Queue<Item> other)这样的实例方法,我就无法访问其他节点,因为它是私有的。如果我尝试编写静态方法public static Queue<Item> catenante(Queue<Item> a, Queue<Item> b),我会遇到同样的问题。

1 个答案:

答案 0 :(得分:1)

为了完整起见,这是一个简单的实现。串联与您打算实现的方式不同,以免破坏问题。实现的作用是显示Access Modifiers的各种用法,特别是声明为private的变量仍然可以从它声明的类中访问,而不管它是否属于试图访问它的同一个Object。这在以下访问级别表中列出:Access Levels

这表明声明为private的变量只能在声明它的类中访问。

关于访问修饰符的目的;他们没有明确地为了“安全目的”保护信息。他们在面向对象编程中扮演着一个角色来封装实现;阻止直接访问。请记住,使用Encapsulation,您可以限制对数据的直接访问,同时提供允许您与此类数据交互的方法。我发现Encapsulation的主要原因是避免滥用类;例如,用户可能会尝试将最后一个Node变量调整为null,这会在下面的代码中引发许多错误。 Getters和Setter是允许各种类与属于类的数据交互的完美合法方式,同时仍然可以确保封装,因为您可以限制变量的更新方式。

public class Queue<Item> {
    private Node<Item> first;
    private Node<Item> last;

    private static class Node<Item> {
        private Item item;
        private Node<Item> next;

        public Node (Item item) {
            this.item = item;
        }
    }

    /* Add node to Queue */
    public void add (Item item) {
        Node<Item> node = new Node(item);
        if (last == null) {
            this.first = node;
            this.last = node;
        } else {
            last.next = node;
            this.last = node;
        }
    }

    /* Static concatenate method */
    public static <Item> Queue concatenate (Queue<Item> A, Queue<Item> B) {
        Queue<Item> copyA = A.copy();
        Queue<Item> copyB = B.copy();
        copyA.last.next = copyB.first;
        return copyA;
    }

    /* Copy method to perform a Deep clone */
    public Queue<Item> copy() {
        Queue<Item> queue = new Queue<>();
        Node<Item> iter = first;
        while (iter != null) {
            queue.add(iter.item);
            iter = iter.next;
        }
        return queue;
    }

    /* Concatenate method that will modify the item invoking it */
    public void concatenateD1(Queue<Item> toAdd) {
        Queue<Item> copyToAdd = toAdd.copy();
        this.last.next = copyToAdd.first;
        this.last = copyToAdd.last;
    }

    /* Concatenate method that will modify both arrays invoking it */
    public void concatenateD2(Queue<Item> toAdd) {
        this.last.next = toAdd.first;
        this.last = toAdd.last;
    }

    /* Print method to Test */
    public void print() {
        Node<Item> iter = first;
        while (iter != null) {
            System.out.println(iter.item);
            iter = iter.next;
        }
    }
}

缺少Iterable接口的删除和实现,因为它们不是基本实现所必需的。另请注意,有三种连接方法。第一个是concatenate,它是一个静态方法,它将克隆两个队列并将一个队列连接到另一个队列。完成克隆以避免覆盖原始队列。第二个是concatenateD1,它是一个成员方法,它将给定的Queue附加到调用该方法的Queue的末尾。这只会修改调用该方法的队列。最后的concatenateD2也是一个成员方法,它将给定的Queue附加到调用该方法的Queue的末尾。但是,这将修改相关两个队列中的值,因此如果要重用原始对象,则不安全。