栈(Stack)是一种线性数据结构,它遵循“后进先出”(Last In First Out,LIFO)的原则。这意味着最后进入栈的元素将首先被移除,而最先进入栈的元素将被保留在栈的底部。(你就把它看成一个弹夹,里面的元素就好比弹夹里的子弹,最先压入的那颗子弹是不是要最后才能弹出)
栈具有以下特点:
- 插入和删除操作仅在栈的顶部(栈顶)进行,而不影响栈底部的元素。
- 只能访问栈顶的元素,不能直接访问栈中间的元素。
栈在计算机科学中有广泛的应用,如函数调用、表达式求值、内存管理、回溯算法等。一些基本的操作包括:
push
:将元素压入栈顶。pop
:从栈顶移除并返回元素。peek
(或top
):查看栈顶元素但不移除。isEmpty
:检查栈是否为空。
栈可以使用数组或链表来实现。在编程中,栈的应用能够帮助处理各种问题,特别是需要按照特定顺序管理数据时。
以下是栈的实现方式。
还是先定义一个接口:
package main.java.honphie.Interfances;
public interface Stack<E>
{
/**
* 向栈顶压入一个元素
* @param value 压入的元素的值
* @return 如果压入成功返回true,否则返回false
*/
boolean push(E value);
/**
* 从栈顶弹出一个元素
* @return 如果弹出成功返回弹出的元素,否则返回null
*/
E pop();
/**
* 查看栈顶元素
* @return 如果栈顶有元素则返回栈顶元素,否则返回null
*/
E peek();
/**
* 获取栈中元素的个数
* @return 栈中元素的个数
*/
// int size();
/**
* 判断栈是否为空
* @return 如果栈为空返回true,否则返回false
*/
boolean isEmpty();
/**
* 判断栈是否已满
* @return 如果栈已满返回true,否则返回false
*/
boolean isFull();
}
这次先用链表来实现:
public class LinkedListStack<E> implements Stack<E>, Iterable<E> {
private int capacity;//栈的容量
private int size;//栈中元素的个数
private Node<E> head = new Node<>(null, null);//头结点
/**
* 链表节点类
* @param <E> 节点值的类型
*/
static class Node<E>
{
E value;
Node<E> next;
Node(E value, Node<E> next) {
this.value = value;
this.next = next;
}
}
/**
* 构造方法
* @param capacity 栈的容量
*/
public LinkedListStack(int capacity) {
this.capacity = capacity;
}
/**
* 实现push方法,向栈顶压入一个元素
* @param value 压入的元素的值
* @return 如果压入成功返回true,否则返回false
*/
@Override
public boolean push(E value)
{
if(isFull())
{
return false;
}
head.next = new Node<>(value, head.next);
size++;
return true;
}
/**
* 实现pop方法,从栈顶弹出一个元素
* @return 如果弹出成功返回弹出的元素,否则返回null
*/
@Override
public E pop()
{
if (isEmpty())
{
return null;
}
Node<E> first = head.next;
head.next = first.next;
size--;
return first.value;
}
/**
* 实现peek方法,查看栈顶元素
* @return 如果栈顶有元素则返回栈顶元素,否则返回null
*/
@Override
public E peek() {
if (isEmpty())
{
return null;
}
return head.next.value;
}
/**
* 实现isEmpty方法,判断栈是否为空
* @return 如果栈为空返回true,否则返回false
*/
@Override
public boolean isEmpty() {
return size == 0;
}
/**
* 实现isFull方法,判断栈是否已满
* @return 如果栈已满返回true,否则返回false
*/
@Override
public boolean isFull() {
return size == capacity;
}
/**
* 实现iterator方法,返回一个迭代器
* @return 一个迭代器
*/
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
Node<E> p = head;
/**
* 实现hasNext方法,判断是否还有下一个元素
* @return 如果还有下一个元素返回true,否则返回false
*/
@Override
public boolean hasNext() {
return p != null;
}
/**
* 实现next方法,返回下一个元素
* @return 下一个元素
*/
@Override
public E next() {
E value = p.value;
p = p.next;
return value;
}
};
}
}
再用数组来实现,数组的话将最后一个元素作为栈顶。
public class ArrayStack<E> implements Stack<E>,Iterable<E>{
private E[] array;
private int top;//栈顶指针,在数组的最后一个元素
public ArrayStack(int capacity){
array = (E[]) new Object[capacity];
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
private int i = top;
/**
* 判断是否还有下一个元素
* @return 如果还有下一个元素返回true,否则返回false
*/
@Override
public boolean hasNext() {
return i > 0;
}
/**
* 获取下一个元素
* @return 下一个元素
*/
@Override
public E next() {
return array[--i];//i--是错误的,因为i--是先取i的值,再自减
}
};
}
/**
* 实现push方法,向栈顶压入一个元素
* @param value 压入的元素的值
* @return 如果压入成功返回true,否则返回false
*/
@Override
public boolean push(E value) {
if (isFull())
{
return false;
}
array[top++] = value;
return true;
}
/**
* 实现pop方法,从栈顶弹出一个元素
* @return 如果弹出成功返回弹出的元素,否则返回null
*/
@Override
public E pop() {
if (isEmpty())
{
return null;
}
return array[--top];
}
/**
* 实现peek方法,查看栈顶元素
* @return 如果栈顶有元素则返回栈顶元素,否则返回null
*/
@Override
public E peek() {
if (isEmpty())
{
return null;
}
return array[top - 1];
}
/**
* 实现isEmpty方法,判断栈是否为空
* @return 如果栈为空返回true,否则返回false
*/
@Override
public boolean isEmpty() {
return top == 0;
}
/**
* 实现isFull方法,判断栈是否已满
* @return 如果栈已满返回true,否则返回false
*/
@Override
public boolean isFull() {
return top == array.length;
}
}