前言
栈在工程中有大量的应用,而在算法中相对简单,而且在很多时候,该数据结构都是解决更高级问题的工具,可以直接使用,这里我们先理解栈的特征,实现原理已经在算法中如何应用。
提示:以下是本篇文章正文内容,下面案例可供参考
一、栈基础知识
1.1 栈的特征
栈是一种数据结构,它遵循"先进后出"(Last In First Out,LIFO)的原则。栈可以看做是一种特殊的线性表(访问受限的线性表),只能在表的一端进行插入和删除操作,这一端被称为栈顶(Top),另一端被称为栈底(Bottom),同时把插入元素的操作称为入栈(Push),删除元素的操作称为出栈(Pop)
栈的特点如下:
- 只能在栈顶进行插入和删除操作,即元素的添加和移除只能发生在同一位置。
- 最后插入的元素将成为第一个被删除的元素,因此,栈的插入和删除操作是按照后进先出顺序进行的。
- 栈的大小有限,当栈满时,无法继续插入新的元素;当栈为空时,无法进行删除操作。
1.2 栈的应用场景很广泛,例如:
- 程序调用栈:在计算机编程中,函数调用和退回是通过使用栈来管理的。
- 括号匹配:利用栈的特性,可以判断一个表达式中的括号是否匹配。
- 浏览器历史记录:浏览器通过使用栈来记录用户访问的网页,用户可以通过后退按钮来回退到之前访问的网页。
1.3 栈的操作
栈有许多操作,常见的有:
- 入栈:push(E),
- 出栈:pop(),
- 获取栈顶元素,出栈:pop(),
- 显示栈顶元素,不出栈:peek()
- 判断栈是否为空:empty()
通过这些操作,可以方便地对栈进行操作和管理。
1.4 Java中的栈
Java中提供了现成的数据结构实现,如java.util.Stack类,它使用向量(Vector)作为底层实现,向量本质上也是使用数组实现的动态数组。此外,Java中也可以自行实现栈的数据结构,使用数组或链表作为底层实现,根据需求选择合适的实现方式。
代码如下:
public class MainTest {
public static void main(String[] args) {
Stack<Integer> stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println("栈顶元素为:" + stack.peek());
while (!stack.empty()) {
//只显示没出栈
System.out.println(stack.peek());
//出栈并且显示
System.out.println(stack.pop());
}
}
}
2.基于数组实现栈
代码如下:
class Arraystack<T> {
//实现栈的数组
private Object[] stack;
//栈顶元素
private int top;
Mystack() {
//初始容量为10
stack = new Object[10];
}
//判断是否为空
public boolean isEmpty() {
return top == 0;
}
//返回栈顶元素
public T peek() {
T t = null;
if (top > 0)
t = (T) stack[top - 1];
return t;
}
public void push(T t) {
expandCapacity(top + 1);
stack[top] = t;
top++;
}
//出栈
public T pop() {
T t = peek();
if (top > 0) {
stack[top - 1] = null;
top--;
}
return t;
}
//扩大容量
public void expandCapacity(int size) {
int len = stack.length;
if (size > len) {
size = size * 3 / 2 + 1;//每次扩大50%
stack = Arrays.copyOf(stack, size);
}
}
}
3.基于链表实现栈
基于链表实现栈可能就稍微比数组复杂一点,将链表的头结点设为栈顶,每次出栈,入栈,都对head节点进行操作。
代码如下:
class ListStack<T> {
//定义链表
class Node<T> {
public T t;
public Node next;
}
public Node<T> head;
//构造函数初始化头指针
ListStack() {
head = null;
}
//入栈
public void push(T t) {
if (t == null) {
throw new NullPointerException("参数不能为空");
}
if (head == null) {
head = new Node<T>();
head.t = t;
head.next = null;
} else {
Node<T> temp = head;
head = new Node<>();
head.t = t;
head.next = temp;
}
}
//出栈
public T pop() {
if (head == null) {
return null;
}
T t = head.t;
head = head.next;
return t;
}
//取栈顶元素
public T peek() {
if (head == null) {
return null;
}
T t = head.t;
return t;
}
//栈空
public boolean isEmpty() {
if (head == null)
return true;
else
return false;
}
}
总结
要学好算法, 就要对常用的数据结构有一定的了解,这样在遇到问题的时候,我们才能选择合适的数据结构去实现。