数据结构与算法—数组栈和链表栈

@TOC

栈介绍

数据结构与算法—数组栈和链表栈_System

  • 栈,存储货物或供旅客住宿的地方,可引申为仓库、中转站,所以引入到计算机领域里,就是指数据暂时存储的地方,所以才有进栈出栈的说法。
  • 栈是一种受限线性表,也就是说,栈元素具有线性关系,即前驱后继关系;只不过它是 一种特殊的线性表而已;
  • 线性表是在表尾进行插入和删除操作,而在栈中表尾是指栈顶,而不是栈底;栈的数据操作始终只在栈顶进行,即先进后出,后进先出;

栈图解

现有五个元素要进入栈中分别:1、2、3、4、5。注:元素进入栈称为"压栈"

数据结构与算法—数组栈和链表栈_System_02

进入后发现先进入的到了最下面,离出口最远。而最后进入的却在最上面,离出口最近

数据结构与算法—数组栈和链表栈_压栈_03

现需要对栈中数据进行取出,看看情况会是什么样。 注:栈取出元素称为" 弹栈"

数据结构与算法—数组栈和链表栈_System_04

可以发现最先出来的是(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
*/

单链表实现栈

实现思路(图解)

数据结构与算法—数组栈和链表栈_System_05

实现代码

链表节点类

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
*/

栈总结

前面我们说过,栈是一个线性表。所以,任何实现表的方法都可以用来实现栈

记住本文章的几个关键字:,"先进后出,后进先出",压栈弹栈栈顶栈底,你已经对栈有基本的了解了。

栈力扣

🌈以后关于栈的力扣题就关联在这下面把