一、什么是栈
栈的特性:后进先出、先进后出
栈的基本操作:
- push(E):增加一个元素E
- pop0:弹出元素E
- peek0:显示栈顶元素,但是不出栈
- empty0:判断栈是否为空
二、基于数组实现栈
将栈的出入当作数组元素添加和删除,还需要考虑到数组是有长度限制的,所以我们要在入栈前判断是否需要扩容。
import java.util.Arrays;
public class MyStack<T> {
//实现栈的数组
private Object[] stack;
//指向栈顶的上面一个位置 也表示栈的数量
private int top;
//初始化栈,初始容量是10
public MyStack(){
stack = new Object[10];
}
//入栈
public void push(T t) {
expandCapacity(top + 1);
stack[top] = t;
top++;
}
//显示栈顶元素
public T peek() {
T t = null;
if (top > 0) {
t = (T) stack[top - 1];
}
return t;
}
//出栈
public T pop() {
T t = peek();
if (top > 0) {
top--;
stack[top] = null;
}
return t;
}
//判空
public boolean isEmpty() {
return top == 0;
}
//扩大容量
private void expandCapacity(int size) {
int len = stack.length;
if (size > len) {
size = size * 3 / 2 + 1; //扩容1.5倍
Arrays.copyOf(stack, size);
}
}
}
三、基于链表实现栈
基于链表实现栈就是将新元素添加在表头,那么在出栈的的时候就会将后放入的节点取出来。
实现:维护一个虚礼表头,使入栈的元素添加到虚礼表头的next,出栈时取出虚礼表头的next并删除。
public class ListStack<T> {
class Node{
T t;
Node next;
public Node(T t) {
this.t = t;
}
}
//虚礼头节点
private Node dummyNode;
public ListStack() {
this.dummyNode = new Node(null);
}
//入栈
public void push(T t){
Node node = new Node(t);
node.next = dummyNode.next;
dummyNode.next = node;
}
//显示栈顶元素
public T peek(){
T t = null;
if (!isEmpty()){
t = dummyNode.next.t;
}
return t;
}
//出栈
public T pop(){
T t = peek();
if (!isEmpty()){
dummyNode.next = dummyNode.next.next;
}
return t;
}
//判空
public boolean isEmpty(){
return dummyNode.next == null;
}
}
四、使用双向链表实现栈
以LinkedList作为底层数据结构实现栈时,我们利用其特性:可以从链表的头部(或尾部)高效地插入和删除元素。维护一个LinkedList对象来存储栈中的元素。
import java.util.LinkedList;
public class LinkedListStack<T> {
private LinkedList<T> linkedList;
public LinkedListStack() {
linkedList = new LinkedList<>();
}
//入栈
public void push(T t){
linkedList.addFirst(t);
}
//显示栈顶元素
public T peek(){
return linkedList.peekFirst();
}
//出栈
public T pop(){
return linkedList.removeFirst();
}
//判空
public boolean isEmpty(){
return linkedList.isEmpty();
}
}