数据结构与算法—数组栈和链表栈
@TOC
栈介绍
- 栈,存储货物或供旅客住宿的地方,可引申为仓库、中转站,所以引入到计算机领域里,就是指数据暂时存储的地方,所以才有进栈、出栈的说法。
- 栈是一种受限线性表,也就是说,栈元素具有线性关系,即前驱后继关系;只不过它是 一种特殊的线性表而已;
- 线性表是在表尾进行插入和删除操作,而在栈中表尾是指栈顶,而不是栈底;栈的数据操作始终只在栈顶进行,即先进后出,后进先出;
栈图解
现有五个元素要进入栈中分别:1、2、3、4、5。注:元素进入栈称为"压栈"
进入后发现先进入的到了最下面,离出口最远。而最后进入的却在最上面,离出口最近
现需要对栈中数据进行取出,看看情况会是什么样。 注:栈取出元素称为" 弹栈"
可以发现最先出来的是(5),也就是最后进入的元素。以此类推,最后出来的则是(1)最先进入的元素。
这时候,我们就会发现,栈有 **“先进后出,后进先出”**这个特点。
栈实现
数组实现栈
实现思路
- 用一个数组实现栈是很简单的。每一个栈都有一个top,对于空栈它是-1(这是空栈的初始化)
- 为了将某个元素X压入该栈,我们将top加1,然后置stack[top] =X,其stack是代表具体的栈的数据
- 为了弹出栈元素,我们置返回值为stack[top] ,然后 top减1
实现代码
数组栈 压栈:push()、弹栈:pop()、判满:isFull()、判空:isEmpty()、遍历:list()等方法
ArrayStack.java
class ArrayStack{
//最大容量
private int maxSize;
//栈数据组
private int[] stack;
//栈顶
private int top = -1;
//构造器设置最大容量
public ArrayStack(int maxSize) {
this.maxSize = maxSize;
stack = new int[maxSize];
}
//栈满
public boolean isFull(){
//如果top等于最大为栈满
return top == maxSize - 1;
}
//栈空
public boolean isEmpty(){
//如果top等于-1 则为栈空
return top == -1;
}
//添加栈
public void push(int value){
//如果栈满则不添加
if (isFull()){
System.out.println("栈满!!!");
return;
}
//如果没有满则进行栈添加
top++;
stack[top] = value;
}
//取栈值
public int pop(){
//判断栈是否为空
if (isEmpty()){
throw new RuntimeException("栈空!!!");
}
int value = stack[top];
top--;
return value;
}
//遍历栈
public void list(){
//从头到尾
if (isEmpty()){
System.out.println("栈空!!!");
}
for (int i = top; i >=0 ; i--) {
System.out.printf("栈号为%d 值为 %d\n",i,stack[i]);
}
}
}
主程序(测试)
public class ArrayStackDemo {
public static void main(String[] args) {
ArrayStack stack = new ArrayStack(5);
System.out.println("进行压栈~~");
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
stack.push(5);
System.out.println("进行栈遍历~~");
stack.list();
System.out.println("进行弹栈~~");
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
}
}
/* 结果
进行压栈~~
进行栈遍历~~
栈号为4 值为 5
栈号为3 值为 4
栈号为2 值为 3
栈号为1 值为 2
栈号为0 值为 1
进行弹栈~~
5
4
3
2
1
*/
单链表实现栈
实现思路(图解)
实现代码
链表节点类
Node.java
/**
* 链表节点
*/
class Node{
//链表值
private int no;
//单向链表
private Node next;
//构造器
public Node(int no) {
this.no = no;
}
//get set方法
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
链表栈实现类
LinkedStack.java
class LinkedStack{
//头节点
private Node head = new Node(-1);
//栈顶 初始化为-1
private int top =-1;
//栈最大容量
private int maxSize;
//构造器获取最大容量
public LinkedStack(int maxSize) {
this.maxSize = maxSize;
}
//判断栈是否满
public boolean isFull(){
return top == maxSize -1;
}
//判断栈是否为空
public boolean isEmpty(){
return top == -1;
}
//进行栈添加
public void push(Node node){
//先判断栈是否满
if (isFull()){
System.out.println("栈满!!!");
}
//第一次进行添加特殊,如果top == -1 说明第一次添加
if (top == -1){
head.setNext(node);
top++;
return;
}
//如果不是第一次添加则进行添加逻辑
Node temp = head;
//将其他节点后移
node.setNext(temp.getNext());
//再将插入值连接到头节点
temp.setNext(node);
//栈顶++
top++;
}
//进行取栈值
public Node pop(){
//先判断是否为空栈
if (isEmpty()){
throw new RuntimeException("栈为空!!!");
}
//如果不为空则进行取栈
Node temp = head;
Node value = temp.getNext();
//将节点删除
temp.setNext(value.getNext());
top--;
return value;
}
//进行栈遍历
public void list(){
//判断是否为空栈
if (isEmpty()){
System.out.println("栈为空!!!");
}
Node temp = head;
//进行栈遍历
for (int i = 0; i <= top; i++) {
System.out.printf("栈值为:%d\n",temp.getNext().getNo());
//临时指针进行后移
temp = temp.getNext();
}
}
}
主程序(测试)
public class LinkedStackDemo {
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
LinkedStack linkedStack = new LinkedStack(5);
System.out.println("链表栈进行添加!!!");
linkedStack.push(node1);
linkedStack.push(node2);
linkedStack.push(node3);
linkedStack.push(node4);
linkedStack.push(node5);
System.out.println("链表栈遍历!!!");
linkedStack.list();
System.out.println("链表栈取出!!!");
System.out.println(linkedStack.pop().getNo());
System.out.println(linkedStack.pop().getNo());
System.out.println(linkedStack.pop().getNo());
System.out.println(linkedStack.pop().getNo());
System.out.println(linkedStack.pop().getNo());
System.out.println("取完以后查看链表情况!!!");
linkedStack.push(node1);
linkedStack.push(node2);
linkedStack.pop();
linkedStack.list();
}
}
/* 结果
链表栈进行添加!!!
链表栈遍历!!!
栈值为:5
栈值为:4
栈值为:3
栈值为:2
栈值为:1
链表栈取出!!!
5
4
3
2
1
取完以后查看链表情况!!!
栈值为:1
*/
栈总结
前面我们说过,栈是一个线性表。所以,任何实现表的方法都可以用来实现栈。
记住本文章的几个关键字:栈,"先进后出,后进先出",压栈,弹栈,栈顶,栈底,你已经对栈有基本的了解了。
栈力扣
🌈以后关于栈的力扣题就关联在这下面把