【问题标题】:Generics in Java (Queue)Java 中的泛型(队列)
【发布时间】:2021-09-03 20:50:21
【问题描述】:

我实现了一个堆栈类。

现在,我想基于该堆栈创建一个队列。像这样:

public class Queue<E> {

    private Stack<E> next;
    private Stack<E> next2;

    public E first() {
        
    }
    public Queue<E> enqueue(E e) {
        
    }
    public Queue<E> dequeue() {
        
    }
    public boolean isEmpty() {
        if (this.next == null) {
            return true;
        }
        if (Stack.isEmpty(next)) {
            return true;
        }
        return false;
    }

}

我不知道从哪里开始。我怎么解决这个问题?我的第一个想法是在 Stack 中使用“reverse”方法。但我不确定。

【问题讨论】:

  • 您的Stack 类没有实例方法。 private Stack&lt;E&gt; next = Stack.create(); 给你一个Stack,然后你可以用你的static 方法将pushpop 放到上面。不理想。
  • 好吧,当你想插入队列时,你可以弹出另一个堆栈中的所有内容,然后插入原始堆栈,将 tmp 堆栈的所有内容推送到原始堆栈。 Pop 完成正常

标签: java generics queue stack


【解决方案1】:

有两种方法可以做到这一点。第一个是使用反向函数在堆栈末尾推送。像这样

public class Queue<E> {

    private Stack<E> next;

    public E front() {
        return (E) Stack.<E>top(next);
    }
    public Queue<E> enqueue(E e) {
        Stack<E> nextNew = Stack.reverse(next);
        nextNew = Stack.push(nextNew, e);
        nextNew = Stack.reverse(nextNew);
        Queue<E> q = new Queue<E>();
        q.next = nextNew;
        return q;
    }
    public Queue<E> dequeue() {
        Stack<E> nextNew = Stack.pop(next);
        Queue<E> q = new Queue<E>();
        q.next = nextNew;
        return q;
    }
    public boolean isEmpty() {
        if (this.next == null) {
            return true;
        }
        if (Stack.isEmpty(next)) {
            return true;
        }
        return false;
    }
}

【讨论】:

  • 感谢您的回答!我上传了我的代码的基本结构。你能告诉我你的意思吗(也许编辑我的代码)?
  • 嗯。好吧,我认为您无法按照设置结构的方式进行操作。队列需要有整个堆栈。然后插入(我猜那是排队)应该插入你拥有的那个堆栈中。出队应该从堆栈中删除。但不同之处在于您需要 FIFO 而不是 LIFO 顺序。所以我可以根据你的 Stack 键入一个队列,但它会与你刚刚发送的队列不同
  • 问题是我不能使用多个私有属性。方法签名给了我。我不应该改变它们。我可以使用 Stack 中的 reverse 方法将 LIFO 反转为 FIFO
  • 哦。好吧。这改变了它。你可以只推然后反转。总是这样做,就是这样。试试看
  • 你能给我一个例子吗?所有这些操作都基于堆栈,但是例如dequeue 有 Queue&lt;E&gt; 作为返回类型而不是 Stack。
【解决方案2】:

我认为递归是最巧妙的:

public class Queue<E> {

    private Stack<E> stack;

    public Queue(Stack stack) {
        this.stack = stack;
    }

    public E front() {
        return Stack.top(stack);
    }

    public Queue<E> enqueue(E newValue) {
        if (Stack.top(stack) == null) {
          return new Queue(Stack.push(Stack.create(), newValue));
        }
        return new Queue<>(Stack.push(new Queue(Stack.pop(stack)).enqueue(newValue).stack, Stack.top(stack)));
    }

    public Queue<E> dequeue() {
        return new Queue<>(Stack.pop(stack));
    }

    public String toString() {
        return "Q: " + stack.toString();
    }
}

请注意,不需要反转。

我认为 Stack 类中的某些代码对于“a”参数和额外变量有点不清楚,所以我对其进行了一些重构,并删除了所有未使用的内容。我还添加了一个toString(),它递归地遍历堆栈:

public class Stack<E> {

    private final E value;
    private final Stack<E> next;

    private Stack(E value, Stack<E> next) {
        this.value = value;
        this.next = next;
    }

    public static <E> Stack<E> create() {
        return new Stack<>(null, null);
    }

    public static <E> Stack<E> push(Stack<E> stack, E newValue) {
        return new Stack<E>(newValue, stack);
    }

    public static <E> Stack<E> pop(Stack<E> stack) {
        if (stack == null) {
            return new Stack<E>(null, null);
        } else if (stack.value == null) {
            return new Stack<>(null, null);
        } else if (stack.next == null) {
            return new Stack<E>(null, null);
        } else {
            return stack.next;
        }
    }

    public static <E> E top(Stack<E> stack) {
        if (stack == null) {
            return null;
        } else if (stack.value == null) {
            return null;
        } else {
            return stack.value;
        }
    }

    public String toString() {
        if (Stack.top(next) == null) {
            return (value != null ? value.toString() : "Null");
        }
        return (value != null ? value.toString() : "Null") + " " + next.toString();
    }
}

还有一点测试课。为了显示堆栈和队列之间的区别,它首先加载一个堆栈,然后将它传递给一个队列并添加更多元素,然后从前面拉一些:

public class QueueWithStackMain {
    public static void main(String[] args) {
        Stack<String> stack = Stack.create();
        stack = Stack.push(stack, "1");
        System.out.println(stack.toString());
        stack = Stack.push(stack, "2");
        System.out.println(stack.toString());
        stack = Stack.push(stack, "3");
        System.out.println(stack.toString());
        Queue<String> queue = new Queue<>(stack);
        System.out.println(queue.toString());
        queue = queue.enqueue("4");
        System.out.println(queue.toString());
        queue = queue.enqueue("5");
        System.out.println(queue.toString() + " -> " + queue.front());
        queue = queue.dequeue();
        System.out.println(queue.toString() + " -> " + queue.front());
    }
}

【讨论】:

  • 我认为他无法更改堆栈或向队列添加新方法。
  • @Dusan Todorovic 他改变了问题。我重构 Stack 只是为了清楚起见,根本没有改变它的功能,我添加到 Queue 的唯一方法是构造函数。
  • 我做了一个快速更新。 enqueue() 方法过于复杂,因为它没有将递归一直到 Null Stack。一旦完成,它就变得微不足道了。整个 Queue 类现在只有 25 行 - 包括 toString()。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多