目录
概念
是一种线性的数据结构,只能在其一端添加数据和移除数据。习惯来说,这一端称之为栈顶,另一端不能操作数据的称之为栈底。特点是先进后出。
简单接口,待会我们的两种实现方式都需要实现该接口。
public interface Stack<E> {
/**
* 压入元素
*/
boolean push(E value);
/**
* 弹出元素
*/
E pop();
/**
* 返回栈顶元素但不移除
*/
E peek();
/**
* 判断是否为空
*/
boolean isEmpty();
/**
* 判断是否栈满
*/
boolean isFull();
}
基于链表的实现
由于只有一个出口,因此我们使用单链表就可以实现,首先我们需要清楚的是先进入的后出去,也就是说,最先进入的元素应该是栈底,因此采用头插法。 其次我采用带有哨兵的单链表,这里哨兵节点中的value值可以记录栈中元素数量,但为了方便,我采用了使用size来记录栈中元素数量。
具体实现代码如下
public class LinkedListStack<E> implements Stack<E>, Iterable<E> {
private Node<E> sentinel = new Node<>(null, null);
private int size = 0;
private int capacity = 8;
public LinkedListStack(int capacity) {
this.capacity = capacity;
}
private static class Node<E> {
//采用单链表,只需要next节点
Node<E> next;
E value;
public Node(Node<E> next, E value) {
this.next = next;
this.value = value;
}
}
@Override
public boolean push(E value) {
if (isFull()) {
return false;
}
sentinel.next = new Node<>(sentinel.next, value);
size++;
return true;
}
@Override
public E pop() {
if (isEmpty()) {
return null;
}
Node<E> node = sentinel.next;
sentinel.next = node.next;
size--;
return node.value;
}
@Override
public E peek() {
if (isEmpty()) {
return null;
}
return sentinel.next.value;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public boolean isFull() {
return size == capacity;
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
Node<E> p = sentinel.next;
@Override
public boolean hasNext() {
return p != null;
}
@Override
public E next() {
E value = p.value;
p = p.next;
return value;
}
};
}
}
基于数组的实现
在数组实现的方法中,我们需要一个top指针记录最新出栈的下标位置。实现思路和链表基本一致,难点在于对top指针的更改。我这个实现中,top的值永远等于栈中的元素个数。
具体实现代码如下
public class ArrayStack<E> implements Stack<E>, Iterable<E> {
private int capacity = 8;
private E[] array;
private int top = 0;
@SuppressWarnings("all")
public ArrayStack(int capacity) {
this.capacity = capacity;
array = (E[]) new Object[capacity];
}
@Override
public boolean push(E value) {
if (isFull()) {
return false;
}
//先存储top下标,再top自增
array[top++] = value;
return true;
}
@Override
public E pop() {
if (isEmpty()) {
return null;
}
//top先减1后再获取top下标中的值,这里我没有对被取元素做赋空操作。
return array[--top];
}
@Override
public E peek() {
if (isEmpty()) {
return null;
}
return array[top-1];
}
@Override
public boolean isEmpty() {
return top == 0;
}
@Override
public boolean isFull() {
return top == capacity;
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
int current = top;
@Override
public boolean hasNext() {
return current!=0;
}
@Override
public E next() {
return array[--current];
}
};
}
}