目录
-
自身的特点
- 只能在一端进行删除和插入操作
- 先进后出,后进先出 (栈顶删除数据,栈顶插入数据)
- 数组实现的栈称为顺序栈,链表实现的栈称为链式栈
-
适合解决的问题
- 函数调用栈
- 表达式求值
-
时间复杂度
- 不管是顺序栈还是链栈,时间复杂度都是 O(1)
-
顺序栈和链栈的区别
- 顺序栈: 静态分配存储, 有闲置和溢出的现象
- 链 栈: 动态分配存储, 无闲置和溢出现象 存储利用率高, 元素自由扩充
- 同顺序表和链表, 顺序栈随机读取快, 链栈 插入 删除快
-
代码
-
代码练习1(顺序栈的出入栈)
/**
* 顺序栈实体类
*/
public class SeqEntity {
int[] data;
int top;
public SeqEntity(int size) {
this.data = new int[size];
}
}
/**
* 顺序栈实现类
*/
public class SeqStack implements BaseClass {
protected int mixsize = 10;
protected SeqEntity stack = new SeqEntity(mixsize);
public SeqStack() {
init();
}
// 初始化 Top
public void init() {
stack.top = -1;
}
@Override
public void push(int value) throws Exception {
if (this.isFull()) {
throw new Exception("***满栈***");
}
stack.top++;
stack.data[stack.top] = value;
}
@Override
public int pop() throws Exception {
if (this.isEmpty()) {
throw new Exception("***空栈***");
}
int returnData = stack.data[stack.top];
stack.data[stack.top] = 0;
stack.top--;
return returnData;
}
@Override
public boolean isEmpty() {
if (stack.top == -1) {
return true;
}
return false;
}
@Override
public boolean isFull() {
if ((stack.top - 1) == mixsize) {
return true;
}
return false;
}
public static void main(String[] args) throws Exception {
SeqStack seqStack = new SeqStack();
System.out.println("***开始入栈***");
seqStack.push(2);
seqStack.push(3);
System.out.println(seqStack.stack.top);
System.out.println(Arrays.toString(seqStack.stack.data));
System.out.println("***开始出栈***");
seqStack.pop();
System.out.println(seqStack.stack.top);
System.out.println(Arrays.toString(seqStack.stack.data));
}
}
-
代码练习2(链栈反转数组)
/**
* 栈 反转数组
* 思路 : 先将数组顺序入栈, 再将栈顺序出栈到新数组
*/
public class InvertArray extends SeqStack {
int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9};
protected int mixsize = array.length;
public static void main(String[] args) throws Exception {
InvertArray stack = new InvertArray();
for (int i : stack.array) {
stack.push(i);
}
int[] array_new = new int[stack.mixsize];
for (int i = 0; i < stack.mixsize; i++) {
array_new[i] = stack.pop();
}
System.out.println(Arrays.toString(array_new));
}
}
-
代码练习3(链栈新增删除)
/**
* 描述链栈节点的数据结构
*/
public class LinkStackNodeEntity {
/**
* 数据域
*/
private int data;
/**
* 指针域 指向上一个节点
*/
private LinkStackNodeEntity next;
public LinkStackNodeEntity(int value) {
this.data = value;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public LinkStackNodeEntity getNext() {
return next;
}
public void setNext(LinkStackNodeEntity next) {
this.next = next;
}
}
/**
* 链栈结构体
*/
public class LinkStackEntity {
/**
* 描述栈顶, 总是指向最后入栈的节点
*/
private LinkStackNodeEntity top;
/**
* 描述栈的总长度 或说成 链表有几个节点
*/
private int size;
public LinkStackNodeEntity getTop() {
return top;
}
public void setTop(LinkStackNodeEntity top) {
this.top = top;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
/**
* 链栈实现类
*/
public class LinkStack implements BaseClass {
LinkStackEntity stack = new LinkStackEntity();
public LinkStack() {
init();
}
/**
* 初始化
*/
public void init() {
stack.setSize(0);
stack.setTop(null);
}
@Override
public void push(int value) throws Exception {
LinkStackNodeEntity node = new LinkStackNodeEntity(value);
node.setNext(stack.getTop());
stack.setTop(node);
stack.setSize(stack.getSize() + 1);
}
@Override
public int pop() throws Exception {
if (this.isEmpty()) {
throw new Exception("***空栈***");
}
int returnData = stack.getTop().getData();
// 栈顶指向栈顶元素的下一个元素(next指向的元素)
stack.setTop(stack.getTop().getNext());
stack.setSize(stack.getSize() - 1);
return returnData;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean isFull() {
// 链栈是存储空间动态分配的, 没有满栈的情况
return false;
}
/**
* 打印单链表中的每个元素
*
* @param node
* @return
*/
public ArrayList<Integer> printNode(LinkStackEntity node) throws Exception {
ArrayList array = new ArrayList<Integer>();
LinkStackNodeEntity tmp = node.getTop();
if (node == null) {
throw new Exception("***传入的链表为空***");
}
while (tmp.getNext() != null) {
array.add(tmp.getData());
tmp = tmp.getNext();
}
array.add(tmp.getData());
return array;
}
public static void main(String[] args) throws Exception {
LinkStack myStack = new LinkStack();
System.out.println("***入栈***");
myStack.push(1);
myStack.push(2);
myStack.push(3);
myStack.push(4);
System.out.println("栈的长度为" + myStack.stack.getSize());
System.out.println(myStack.printNode(myStack.stack));
System.out.println("***出栈***");
int popValue = myStack.pop();
System.out.println("出栈的值为:"+popValue);
System.out.println("栈的长度为:" + myStack.stack.getSize());
System.out.println(myStack.printNode(myStack.stack));
}
}
-
练习代码4(通过栈实现浏览器前进、后退)
/**
* 练习题: 实现浏览器 前进、后退 动作
* 场景会频繁的插入、删除, 选择链栈
* 个人理解:
* 浏览器前进操作事件 --> 数据入栈 并 后退栈出栈
* 浏览器后退操作事件 --> 数据出栈 并 前进栈入栈
*/
public class Exercises01 {
/**
* 记录后退节点的栈
*/
LinkStackEntity backwardStack;
/**
* 记录前进节点的栈 -- 前提是后退过
*/
LinkStackEntity forwardStack;
public Exercises01() {
init();
}
/**
* 初始化两个栈
*/
public void init() {
backwardStack = new LinkStackEntity();
forwardStack = new LinkStackEntity();
backwardStack.setTop(null);
forwardStack.setTop(null);
backwardStack.setSize(0);
forwardStack.setSize(0);
}
/**
* 处理后退事件
*
* @throws Exception
*/
public void on_backward() throws Exception {
if (isEmpty(forwardStack)) {
throw new Exception("没有可退的节点了");
} else {
int value = pop(forwardStack);
push(backwardStack, value);
}
}
/**
* 处理前进事件
*
* @return
* @throws Exception
*/
public void on_forward(int value) throws Exception {
// 前进事件栈 --> 数据入栈
push(forwardStack, value);
if (!isEmpty(backwardStack)) {
// 后退事件栈 数据出栈
pop(backwardStack);
}
}
/**
* 入栈
*
* @param stack
* @param value
*/
public void push(LinkStackEntity stack, int value) {
LinkStackNodeEntity node = new LinkStackNodeEntity(value);
node.setNext(stack.getTop());
stack.setTop(node);
stack.setSize(stack.getSize() + 1);
}
/**
* 出栈
*
* @param stack
* @throws Exception
*/
public int pop(LinkStackEntity stack) throws Exception {
if (isEmpty(stack)) {
throw new Exception("空栈");
}
int pop_value = stack.getTop().getData();
stack.setTop(stack.getTop().getNext());
stack.setSize(stack.getSize() - 1);
return pop_value;
}
/**
* 栈 是否为空
*
* @param stack
* @return true 空 , false 非空
*/
public boolean isEmpty(LinkStackEntity stack) {
if (stack.getSize() == 0) {
return true;
}
return false;
}
}