栈(Stack)是一种特殊的线性数据结构,其特性是“后进先出”(LIFO,Last In First Out)。它只允许在一端(称为栈顶,Top)进行插入和删除操作。
栈结构的概念
栈是由一系列元素组成的数据集合,这些元素遵循后进先出(LIFO)的原则。栈的主要操作包括:
push(element)
: 把元素压入栈顶。pop()
: 弹出栈顶元素,并返回该元素。peek()
: 返回栈顶元素,但不删除它。isEmpty()
: 判断栈是否为空。isFull()
: 判断栈是否已满(这取决于栈的实现方式和可用的存储空间)。clear()
: 清空栈。
栈结构的特点
- 后进先出(LIFO):最后入栈的元素最先出栈。
- 栈底(Bottom):栈的起始位置,栈底元素是第一个入栈的元素,也是唯一不能从栈中删除的元素(除非栈被清空)。
- 栈顶(Top):栈的当前末端位置,栈顶元素是最后一个入栈的元素,也是下一个出栈的元素。
栈的代码实现
以下是使用Java实现栈的示例代码,包括准备数据、初始化栈结构、判断空栈、判断栈满(针对固定大小的栈实现)、清空栈、释放空间(在Java中通常通过垃圾回收自动处理)、入栈、出栈和读栈顶数据等操作:
public class Stack<T> { | |
private Object[] elements; | |
private int size; | |
private int capacity; | |
// 初始化栈,可指定容量 | |
public Stack(int capacity) { | |
this.capacity = capacity; | |
this.elements = new Object[capacity]; | |
this.size = 0; | |
} | |
// 默认初始化栈,容量为10 | |
public Stack() { | |
this(10); | |
} | |
// 判断栈是否为空 | |
public boolean isEmpty() { | |
return size == 0; | |
} | |
// 判断栈是否已满(仅针对固定大小的栈) | |
public boolean isFull() { | |
return size == capacity; | |
} | |
// 入栈操作 | |
public void push(T item) { | |
if (isFull()) { | |
throw new IllegalStateException("Stack is full"); | |
} | |
elements[size++] = item; | |
} | |
// 出栈操作 | |
public T pop() { | |
if (isEmpty()) { | |
throw new IllegalStateException("Stack is empty"); | |
} | |
return (T) elements[--size]; | |
} | |
// 读栈顶数据 | |
public T peek() { | |
if (isEmpty()) { | |
throw new IllegalStateException("Stack is empty"); | |
} | |
return (T) elements[size - 1]; | |
} | |
// 清空栈 | |
public void clear() { | |
size = 0; | |
} | |
// 释放空间(在Java中,当对象不再被引用时,垃圾回收器会自动处理) | |
// 通常不需要手动释放栈空间 | |
// 获取栈中元素个数 | |
public int size() { | |
return size; | |
} | |
// 打印栈中元素(仅用于调试) | |
@Override | |
public String toString() { | |
StringBuilder sb = new StringBuilder(); | |
sb.append("Stack: ["); | |
for (int i = 0; i < size; i++) { | |
sb.append(elements[i]).append(", "); | |
} | |
if (!isEmpty()) { | |
sb.delete(sb.length() - 2, sb.length()); // 移除最后的逗号和空格 | |
} | |
sb.append("]"); | |
return sb.toString(); | |
} | |
// 主函数,用于测试 | |
public static void main(String[] args) { | |
Stack<Integer> stack = new Stack<>(); | |
// 入栈 | |
stack.push(1); | |
stack.push(2); | |
stack.push(3); | |
// 读栈顶数据 | |
System.out.println("Top element: " + stack.peek()); | |
// 出栈 | |
System.out.println("Popped element: " + stack.pop()); | |
// 判断空栈 | |
System.out.println("Is stack empty? " + stack.isEmpty()); | |
// 清空栈 | |
stack.clear(); | |
System.out.println("Stack after clearing: " + stack); | |
} | |
} |
在上面的代码中,我们定义了一个泛型类Stack<T>
,它可以存储任何类型的对象。我们使用一个Object
数组来存储栈中的元素,并通过size
变量来跟踪栈中的元素数量。我们还提供了判断栈是否为空、是否已满、入栈、出栈、读栈顶数据和清空栈的方法。主函数main
用于演示这些方法的用法。
请注意,在Java中,我们通常不需要手动释放对象占用的空间,因为Java有一个垃圾回收器(Garbage Collector),它会自动回收不再被引用的对象所占用的内存。因此,在上面的代码中,我们没有提供释放空间的方法。