java中队列算法题目_算法:栈和队列题目集合(一)

本文介绍了如何使用栈和队列实现彼此的功能,包括用两个栈实现队列、用两个队列实现栈以及循环队列的实现。详细讲解了每个操作的过程,并给出了具体的Java代码实现。
摘要由CSDN通过智能技术生成

前言

栈和队列是算法的一个基本的知识点之一。这篇文章主要介绍三道有关栈和队列的算法题。因为篇幅所限,只介绍push和pop这两种方法的实现

用栈实现队列

用队列实现栈

循环队列的实现

用栈实现队列

入队列的功能我们可以用栈的入栈的功能替代。但问题在于出队列的功能怎么实现。

这里有一个问题,就是栈是后入先出的,队列是先进先出的,两者出入的方式不一样。

那么怎么实现方向的一致呢? 我们可以使用两个栈,一个栈用于输入,一个栈用于输出。当发现输出栈为空的时候,把排列的数据从输入栈一个个弹出,“倒入”到 输出栈中,这样的话,数据排列的方向就刚好被逆转过来了,原本在输入栈中处于栈底的数据被置换到输出栈的栈顶,这时候对它出栈也就同时完成了队列的出列的功能。

下面是具体的图示

1.入队列操作: 等同于对入队列进行入栈操作,图示如下

8bcf961cd4fe606bbda4cf1375ed5d91.png

2.出队列操作: 判断当输出栈为空时,先把输入栈的数据依次弹出并加入到输出栈中

4c33b70d4747f9daaab8d451bdc55c1c.png

步骤1

486452322206238d2c6553c64443b816.png

步骤2

对输出栈栈顶进行出栈操作,即可完成出队列功能

e409a4c895f684fb6f4ff0c463430961.png

步骤3

具体代码

import java.util.Stack;

class MyQueue {

private Stack stack1;

private Stack stack2;

private boolean isPushState = true;

/** Initialize your data structure here. */

public MyQueue() {

// 输入栈

stack1 = new Stack();

// 输出栈

stack2 = new Stack();

}

/** Push element x to the back of queue. */

public void push(int x) {

stack1.push(x);

}

public void transformStack () {

if (stack2.empty()) {

while (!stack1.empty()) {

int t = stack1.pop();

stack2.push(t);

}

}

}

/** Removes the element from in front of queue and returns that element. */

public int pop() {

transformStack();

return stack2.pop();

}

/** Returns whether the queue is empty. */

public boolean empty() {

return stack1.empty() && stack2.empty();

}

}

用队列实现栈

这里同样有两个功能需要我们实现,分别是入栈功能和出栈功能

入栈功能

我们可以用入栈操作模拟实现

9d01b467ebd42436bc35b161f76913c9.png

出栈功能

我们又来到了关键功能,这时候你能猜到,我们又需要用到两个队列去实现这个出栈功能了

但问题在于,我们还能否通过讲数据从一个队列“倒”到另一个队列的方式逆转数据方向呢? 这是不行的,因为队列先入先出的特性,导致分割后队列的出入方向仍然是不变的。所以我们要换个思路:

一个元素入队列了,我们接下来希望这个队列像栈一样通过pop把它直接弹出来,但是前面还有很多个元素排着队呢,这时我们想,只要把前面排队的所有元素先出列到另外一个辅助队列里面去,接下来不就可以直接把这个元素踢出队列从而模拟出栈了吗?

6c4930cb7c6ef4eb9f284a6687741011.png

步骤1

770a0f1876ec52a38381105c1eccfa39.png

步骤2

当然完成pop操作后我们还要做一件事情,就是辅助队列和主队列互换,以让未来还能按同样的流程再来一次。

979531612f31a69f99812d20b11e66c6.png

具体代码

import java.util.LinkedList;

import java.util.Queue;

class MyStack {

private Queue queue1;

private Queue queue2;

/** Initialize your data structure here. */

public MyStack() {

queue1 = new LinkedList();

queue2 = new LinkedList();

}

/** Push element x onto stack. */

public void push(int x) {

queue1.offer(x);

}

/** Removes the element on top of the stack and returns that element. */

public int pop() {

while (queue1.size()>1) {

queue2.offer(queue1.poll());

}

int result = (Integer) queue1.poll();

Queue temp =queue1;

queue1 = queue2;

queue2 = temp;

return result;

}

/** Returns whether the stack is empty. */

public boolean empty() {

return queue1.isEmpty();

}

}

循环队列的实现

设计循环队列的原因

对于普通的单向队列,在入队列和出队列的时候可能会遇到一种“队列假满”的现象,导致空间的浪费如下图所示

03263f9dbd9838e8287605c3d5ec1b0b.png

所以我们要做的,就是通过设置头部(front)和尾部(rear)两个指针来区分队列的“满的部分”和“空的部分”,并且允许在填充到数组末尾的时候,能通过回到数组的头部这种循环的方式继续填充数组,从而提高数组空间的利用率。

535714d25957f103ed5e889803eb98ad.png

怎么实现从尾部到头部的循环呢? 我们可以通过取余运算符实现,因为当 i = 数组长度- 1的时候,(i + 1) % 数组长度 = 0,也就是说这个时候指针又从尾部回到了数组的头部

304c7734e423e4bede56fca36bdbbfae.png

具体代码

class MyCircularQueue {

private int [] queue;

private int front;

private int rear;

private int len;

/** Initialize your data structure here. Set the size of the queue to be k. */

public MyCircularQueue(int k) {

queue = new int[k+1];

// 包含

front = 0;

// 不包含

rear = 0;

len = k+1;

}

/** Insert an element into the circular queue. Return true if the operation is successful. */

public boolean enQueue(int value) {

if (isFull()) return false;

queue[rear] = value;

rear =(rear+1) % len;

return true;

}

/** Delete an element from the circular queue. Return true if the operation is successful. */

public boolean deQueue() {

if (isEmpty()) return false;

queue[front] = -1;

front = (front + 1) % len;

return true;

}

/** Get the front item from the queue. */

public int Front() {

if (isEmpty()) return -1;

return queue[front];

}

/** Get the last item from the queue. */

public int Rear() {

if (isEmpty()) return -1;

if (rear>0) return queue[rear-1];

else return queue[len - 1];

}

/** Checks whether the circular queue is empty or not. */

public boolean isEmpty() {

if (rear == front) return true;

else return false;

}

/** Checks whether the circular queue is full or not. */

public boolean isFull() {

if ((rear + 1)%len== front) return true;

else return false;

}

}

b739ec46bb5c46d9c0aa4ce35ba1ea56.png

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[算法:栈和队列题目集合(一)]http://www.zyiz.net/tech/detail-98293.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值