文章目录
🚀 一、 栈
🌟 1.1 栈的概念
栈是一种特殊的线性表,只允许在固定的一端进行插入和删除元素的操作。进行数据插入和删除的一端称为栈顶,另一端叫栈底,栈遵循后入先出原则。
- 压栈:栈的插入操作,入数据在栈顶。
- 出栈:栈的删除操作,出数据在栈顶。
- 栈帧:调用函数时,会为这个函数开辟一块内存,这个内存就是栈帧(在 Java 中,有 Java 虚拟机栈)
1.2 栈的实现
这里使用顺序表实现栈。
public class MyStack {
public int[] elem;
// 当前栈中有效数据个数
public int usedSize;
public MyStack(){
elem = new int[10];
}
/**
* 压栈
* @param val
*/
public void push(int val){
if (isFull()){
elem = Arrays.copyOf(elem,elem.length*2);
}
this.elem[usedSize++] = val;
}
/**
* 判断栈是否满
* @return
*/
public boolean isFull(){
return this.usedSize == elem.length;
}
/**
* 判断栈是否为空
* @return
*/
public boolean isEmpty(){
return this.usedSize == 0;
}
/**
* 出栈
* @return
*/
public int pop(){
return elem[--usedSize];
}
/**
* 获取栈顶元素
* @return
*/
public int peek(){
return elem[usedSize-1];
}
/**
* 获取栈的大小
* @return
*/
public int size(){
return usedSize;
}
public void display(){
for(int i = 0;i<usedSize;i++){
System.out.print(elem[i] + " ");
}
System.out.println();
}
}
🌟 1.3 OJ 题目
🚀 二 、队列
🌟 2.1 概念
队列:只允许一段进行数据插入操作,另一端进行数据删除的特殊线性表,队列遵循先入先出原则。
- 入队列:进行插入操作的一端称为队尾。
- 出队列:进行删除操作的一段称为队头。
🌟 2.2 实现
队列的实现使用链表更加高效。
public class MyQueue {
static class Node{
public int val;
public Node next;
public Node(int val){
this.val = val;
}
}
// 定义队头节点和队尾节点
private Node head = null;
private Node last = null;
public int usedSize = 0;
/**
* 获取队列数据个数
* @return
*/
public int size(){
Node cur = head;
int cnt = 0;
while(cur != null){
cnt++;
cur = cur.next;
}
return cnt;
}
/**
* 入队列
* @param val
*/
public void offer(int val){
Node node = new Node(val);
if(head == null){
head = node;
last = node;
}else {
last.next = node;
last = last.next;
}
usedSize++;
}
/**
* 出队列
*/
public int poll(){
if(head == null){
return -1;
}
int oldVal = head.val;
if(head.next == null){
head = null;
last = null;
}else {
head = head.next;
}
usedSize--;
return oldVal;
}
/**
* 获取队头元素
* @return
*/
public int peek(){
return head.val;
}
}
🚀 三、 循环队列
🌟 3.1 循环队列问题
3.1.1 循环队列数组下标循环的方法:
offset 为步长
- index = ( index + offset) % arr.length
- index = ( index + arr.length - offset ) % arr.length
3.2.2 如何区分队列空满?
- 通过添加一个 usedSize 属性进行记录。
- 保留一个位置,(如下图 rear)
🌟 3.2 循环队列实现
循环队列通常使用数组实现。
public class CircleQueue {
public int[] elem;
public int usedSize;
// 队头和队尾的下标
public int front;
public int rear;
public CircleQueue(){
this.elem = new int[10];
}
/**
* 判断是否为满
* @return
*/
public boolean isFull(){
return usedSize == elem.length;
}
// public boolean isFull2(){
// return (rear+1)% elem.length == front;
// }
/**
* 判断是否为空
* @return
*/
public boolean isEmpty(){
return this.usedSize == 0;
}
// public boolean isEmpty2(){
// return rear == front;
// }
/**
* 入队列
* @param val
* @return
*/
public boolean offer(int val){
if(isFull()){
return false;
}
// 入队列从 rear 入
elem[rear] = val;
// 不能直接 rear++
rear = (rear+1)%elem.length;
this.usedSize++;
return true;
}
/**
* 出队列
* @return
*/
public boolean poll(){
if(isEmpty()){
return false;
}
// 出队列从 front 出
front = (front+1) % elem.length;
usedSize--;
return true;
}
/**
* 获取队尾元素
* @return
*/
public int getRear(){
if(isEmpty()) {
return -1;
}
// 判断 rear 的位置,
int index = rear == 0 ? elem.length-1 : rear-1;
return elem[index];
}
/**
* 获取队头元素
* @return
*/
public int getFront(){
if(isEmpty()) {
return -1;
}
return elem[front];
}
}