栈和队列是比较特殊的线性表,又称之为访问受限的线性表。钱是很多表达式、符号等运算的基础,也是
递归的底层实现。理论上递归能做的题目栈都可以,只是有些问题用栈会非常复杂。
栈底层实现仍然是链表或者顺序表,栈与线性表的最大区别是数据的存取的操作被限制了,其插入和删除
操作只允许在线性表的一端进行。
「栈 Stack」是一种遵循
先入后出
(First In, Last Out)原则的线性数据结构。
图片来源:https://www.hello-algo.com/chapter_stack_and_queue/stack/
栈的操作
- push (E) 增加一个元素 E
- pop()弹出一个元素
- peek()显示栈顶元素,但是不会弹出
- empty()判断栈是否为空
手动实现
再看具体内容之前,先补充一点,top
有的地方指向栈顶元素,有的地方指向栈顶再往上的一个空单位,这
个根据题目要求设计就好,如果是面试的时候就直接问面试官,top
指向到哪里,本文采用指向栈顶空位 置
。
数组
只要注意一点就可以, top-- 和 top - 1 有根本的不同 ! top-- 相当于 top = top - 1
注意 top-- 和 --top 也有区别 !
top--
是先使用top
的值,然后再将top 减 1
。--top
则是先将top 减 1
,然后再使用减 1
后的值
int top = 5;
int result1 = top--; // result1 = 5, top = 4
int result2 = --top; // result2 = 3, top = 3
实现代码
import java.util.Arrays;
/**
* @author leikooo
*/
class Mystack<T> {
/**
* 实现栈的数组
*/
private Object[] stack;
/**
* 栈顶元素
*/
private int top;
Mystack() {
//初始容量为10
stack = new Object[10];
}
/**
* 判断是否为 null
*
* @return
*/
public boolean isEmpty() {
return top == 0;
}
/**
* 返回栈顶元素
*
* @return
*/
public T peek() {
T t = null;
if (top > 0) {
t = (T) stack[--top];
}
return t;
}
/**
* 取出元素
*
* @return
*/
public T pop() {
T t = peek();
if (top > 0) {
stack[top] = null;
}
return t;
}
/**
* 增加元素
*
* @param t
*/
public void push(T t) {
expandCapacity(stack.length);
stack[top] = t;
top++;
}
/**
* 扩大容量
*
* @param size
*/
public void expandCapacity(int size) {
int len = stack.length;
if (size > len) {
// 每次扩大50%
size = size * 3 / 2 + 1;
stack = Arrays.copyOf(stack, size);
}
}
public static void main(String[] args) {
Mystack<String> stack = new Mystack<>();
System.out.println(stack.peek());
System.out.println(stack.isEmpty());
stack.push("java");
stack.push("is");
stack.push("beautiful");
stack.push("language");
// 正在学习日语😎
stack.push("りゆ");
System.out.println(stack.pop());
System.out.println(stack.isEmpty());
System.out.println(stack.peek());
}
}
链表
链表也可以实现栈,插入和删除都在头结点
进行就可以了
/**
* @author leikooo
*/
class ListStack<T> {
//定义链表
class Node<T> {
public T t;
public Node next;
}
public Node<T> head;
//构造函数初始化头指针
ListStack() {
head = null;
}
/**
* 是否为 null
*
* @return
*/
public boolean isEmpty() {
return head == null;
}
/**
* 取出头节点元素
*/
public T peek() {
return (T) head.t;
}
/**
* 入栈
*/
public void push(T t) {
// 初始化需要插入的 节点
Node<T> tNode = new Node<T>();
tNode.t = t;
// 直接替换头节点
tNode.next = head;
head = tNode;
}
/**
* 出栈
* @return
*/
public T pop () {
T peek = peek();
if (head.next == null) {
head = null;
}
head = head.next;
return peek;
}
public static void main(String[] args) {
ListStack stack = new ListStack();
System.out.println(stack.isEmpty());
stack.push("Java");
stack.push("is");
stack.push("beautiful");
System.out.println(stack.peek());
System.out.println(stack.pop());
System.out.println(stack.isEmpty());
}
}