在学习数据结构的时候, 相信大家印象最为深刻的就是栈和队列了吧. 下面我就介绍一下栈和队列吧
1. 栈(Stack)
1.1 栈的概念
栈是一种特殊的线性表, 它只允许在一端进行插入和删除的操作
栈又分为栈顶和栈底
对栈的所有操作都是在栈顶进行的.
栈中的元素必须遵守先进后出的原则: 即先进栈的数据后出栈, 后进栈的数据先出栈.
1.2 进栈和出栈
1.3 栈的实现
由于Java本身就已经封装好了一个 Stack 的类, 因此, 可以直接调用 Stack 中的方法.
如果想要自己实现一个栈, 我们可以通过数组, 来实现一个顺序栈
public class MyStack {
public int[] elem; // 数组
public int top; // 表示当前可以存放数据的下标
public MyStack() {
this.elem = new int[10];
}
// 入栈
public void push(int data) {
// 1. 判断栈是否已满, 若已满, 需要进行扩容
if(full()) {
this.elem = Arrays.copyOf(this.elem, 2*this.elem.length);
}
// 2. 将元素放入栈中
this.elem[top++] = data;
}
// 判断栈是否为空
public boolean empty() {
if(this.top == 0) {
return true;
}
return false;
}
// 判断栈是否已满
public boolean full() {
if(this.elem.length == this.top) {
return true;
}
return false;
}
// 出栈
public int pop() {
// 1. 如果栈为空, 就不能进行出栈
if(!empty()) {
// 2. 栈不为空, 就出栈
// 1. 先拿到栈顶元素
int data = this.elem[this.top - 1];
// 2. 让 top 指向栈顶元素的位置
this.top--;
return data;
}
return -1;
}
// 拿到栈顶元素
public int peek() {
// 1. 栈是否为空, 若为空, 就返回-1
if(!empty()) {
// 2. 若不为空, 就返回栈顶元素
return this.elem[this.top - 1];
}
return -1;
}
public int size() {
return this.top;
}
}
2. 队列(Queue)
2.1 队列的概念
队列也是一个特殊的线性表, 它只允许在一端进行插入操作, 在另一端进行删除操作
队又分为 队头 和 队尾
对于队来说, 从队尾入队, 从队头出队
队中的所有数据元素必须遵守先进先出的原则: 即先入队的先出队, 后入队的后出队
2.2 出队和进队
2.3 队的实现
相同的, java中已经封装好了Queue的接口, 可以直接实现这个接口.
当然, 我们也可以借助链表来实现一个链式队列
class Node {
public int data;
public Node next;
public Node(int data) {
this.data = data;
}
}
public class MyQueue {
public Node front;
public Node rear;
public int usedSize; // 表示队列的长度
// 插入一个元素
public boolean offer(int data){
Node node = new Node(data);
// 1. 第一次插入
if(this.front == null) {
this.front = node;
this.rear = node;
} else {
// 2. 不是第一次插入
this.rear.next = node;
this.rear = this.rear.next;
}
this.usedSize++;
return true;
}
//出队且删除队头元素
public int poll() {
// 1. 判断队是否为空, 若为空, 就返回-1
if(!isEmpty()) {
// 2. 若不为空, 就进行出队
int data = this.front.data;
this.front = this.front.next;
return data;
}
return -1;
}
// 获取队头的元素
public int peek() {
return this.front.data;
}
// 判断队是否为空
public boolean isEmpty() {
if(this.usedSize == 0) {
return true;
}
return false;
}
// 求出 队的长度
public int size() {
return this.usedSize;
}
}
3. 循环队列
3.1 什么是循环队列
循环队列形如下图:
3.2 环形队列的注意事项:
- rear代表的是当前可以存放数据元素的下标
- 环形队列判空的条件是: front == rear
- 环形队列判满的条件是: 通过浪费一个空间, 使得rear的下一个就是front
4. 双端队列(Deque)
4.1 双端队列的概念
双端队列, 就是指两端都允许出队和入队的队列.