@TOC
写在文前
我们今天说的就是下面这两个 Stack 和 Queue,
栈 Stack
栈是一中 先进后出 的数据结构,它的底层是数组,在Java中已经被封装好了,我们可以直接调用,当然我们也可以自己来实现。
一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈
顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则
出栈例题
我们先看一道题目,牢牢掌握如何出栈的
一般这样的是选择题,我们一个一个选项试试就可以了
- A选项 ABCD一次性全部压入栈中,后面一个一个出来就可以了
- B选项 先压入 A 进入后直接出来A 再压B,直接出来B 依次类推
- C选项 压入A B C,出来C,再出B,再出A,最后压入D,直接出来D
- D选项 压入A B C,出来C 后面要出的话只能出来的是B,所以错误
Java中封装的栈方法
我们先使用看看效果,后面自己来实现,不过我们要是使用封装的栈,要导入 import java.util.Stack; 的包
empty()
判断栈是不是空栈
- 空 返回 true
- 不空 返回 false
import java.util.Stack;
public class TestDemo {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>(); // <Integer> 表示 栈中元素是 int 型
System.out.println(stack.empty());
}
}
peek()
返回栈顶的元素,但是不弹出这个元素,如果栈是空栈会抛出一个运行时异常
public static void main1(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(1);
System.out.println(stack.peek());
System.out.println(stack.empty());
}
pop()
返回栈顶的元素,并且弹出这个元素,如果栈是空栈会抛出一个运行时异常
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(1);
System.out.println(stack.pop());
System.out.println(stack.empty());
}
push()
将数据压入栈顶
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(1);
System.out.println(stack.peek());
stack.push(2);
System.out.println(stack.peek());
stack.push(3);
System.out.println(stack.peek());
}
自己实现栈中的方法
栈的底层是一个数组,我们可以选择使用链表或者数组来实现,这里就通过数组的方式,为了简单起见,这里就不进行扩容了
初始工作
public class MyStack {
public int tail; // 标记尾
public int[] elem;
public MyStack() {
this.elem = new int[10]; // 开辟 10 个整型 的空间
this.tail = 0;
}
}
实现 push()
private boolean isFull() {
return this.tail == this.elem.length; //判断是不是满了
}
public void push(int val) {
if(isFull()) {
return; //我们就不扩容了
}
this.elem[this.tail++] = val;
}
实现empty()
public boolean empty() {
return this.tail == 0;
}
实现 peek
public int peek() {
if(empty()) {
throw new RuntimeException("空栈");
}
return this.elem[this.tail-1];
}
实现pop()
public int pop() {
if(empty()) {
throw new RuntimeException("空栈");
}
return this.elem[--this.tail];
}
测试
public class TestDemo {
public static void main(String[] args) {
MyStack myStack = new MyStack();
System.out.println(myStack.empty()); //空栈
myStack.push(1);
System.out.println(myStack.peek());
System.out.println(myStack.empty());
myStack.push(2);
System.out.println(myStack.peek());
System.out.println(myStack.pop());
System.out.println(myStack.pop());
System.out.println(myStack.empty());
}
}
到这里栈的基础知识就说完了,后面就是做题了
队列 Queue
队列和栈是是很相似的数据结构,不过他是 先进先出的模式
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First
In First Out) 入队列:进行插入操作的一端称为队尾(**Tail/Rear**) 出队列:进行删除操作的一端称为队头
java当中的队列也分为几种,下面我就大概shuoyixai
- 双端队列(deque): 是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。
那就说明元素可以从队头出队和入队,也可以从队尾出队和入队 - 循环队列 :操作系统课程讲解生产者消费者模型时可以就会使用循环队列,环形队列通常使用数组实现
Java中封装的队列的方法
这里我们就看一下,后面直接通过链表来实现哎,当然数组也可以
自己实现队列的方法
我们通过 链表 实现
初始工作
class QueueNode {
public int val;
public QueueNode next;
public QueueNode() {
this.val = 0;
this.next = null;
}
public QueueNode(int val) {
this.val = val;
this.next = null;
}
}
public class MyQueue {
private QueueNode head; // 头节点
private QueueNode tail; // 尾节点
public MyQueue() {
this.head = null;
this.tail = null;
}
}
实现add()
public boolean add(int val) {
QueueNode node = new QueueNode(val);
if(this.head==null) {
this.head = node;
this.tail = this.head;
return true;
}
this.tail.next = node;
this.tail = this.tail.next;
return true;
}
实现peek()
public int peek() {
if(this.head==null) {
throw new RuntimeException("空");
}
return this.head.val;
}
实现poll()
public int poll() {
if(this.head==null) {
throw new RuntimeException("空");
}
int ret = this.head.val;
QueueNode cur = this.head;
this.head = this.head.next;
cur.next = null;
return ret;
}
测试
public class TestDemo {
public static void main(String[] args) {
MyQueue myQueue = new MyQueue();
myQueue.add(1);
System.out.println(myQueue.peek());
myQueue.add(2);
System.out.println(myQueue.poll());
System.out.println(myQueue.poll());
}
}