数据结构和算法(七)栈 Stack

news/2025/2/22 23:44:00

1、简介

  1. (Stack)是一个先进后出的有序列表
  2. 是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端为变化的一端,成为顶(Top),另一端为固定的一端,称为底(Bottom)
  3. 根据的定义,最先放入的元素在底,最后放入的元素在顶,删除元素刚好想反,最后放入的元素最先删除,最先放入的元素最后删除
  4. (pop)和入(push)

2、应用场景

  1. 子程序的调用,在跳往子程序前,先将下个指令的地址存入中,直到子程序执行完后再将地址取出,回到原来的程序中
  2. 处理递归调用:和子程序的调用类似,除了存储下一个指令的地址外,也将参数、区域变量等数据存入堆
  3. 表达式的转化(中缀表达式转后缀表达式)与求值
  4. 二叉树的遍历
  5. 图形的深度优先(depth-first)搜索法

3、思路分析

使用数组进行模拟

定义一个 Top 来表示顶,初始化为 -1

有数据入时,top++,stack[top] = data

:int value = stack[top]; top–,return value

4、 Java 代码实现

4.1 数组模拟

public class ArrayStackDemo {
    public static void main(String[] args) {
        ArrayStack arrayStack = new ArrayStack(5);
        arrayStack.push(1);
        arrayStack.push(56);
        arrayStack.push(45);
        arrayStack.push(46);
        arrayStack.list();
        arrayStack.pop();
        arrayStack.pop();
        arrayStack.list();
    }
}

class ArrayStack{
    public int maxSize; // 的大小
    public int[] stack; // 
    public int top = -1; // 

    // 构造
    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }

    // 判断是否为空
    public boolean isEmpty(){
        return top == -1;
    }

    // 判断是否满
    public boolean isFull(){
        return top == maxSize - 1;
    }

    // 入 push
    public void push(int value){
        if(isFull()) {
            System.out.println("已满,无法进行入操作");
            return;
        }
        top ++;
        stack[top] = value;
    }

    // 出 pop
    public void pop(){
        if (isEmpty()) {
            throw new RuntimeException("内没有数据");
        }
        int value = stack[top];
        top --;
        System.out.printf("数据%d已出\n", value);
    }

    // 遍历,从顶开始展示数据
    public void list(){
        if (isEmpty()) {
            System.out.println("内有没数据");
            return;
        }
        for (int i = top; i >= 0; i--) {
            System.out.printf("stack[%d] = %d\n", i, stack[i]);
        }
    }

}

4.2 链表模拟

public class LinkedListStackDemo {
    public static void main(String[] args) {
        LinkedStack linkedStack = new LinkedStack();
        linkedStack.push(new Node(1));
        linkedStack.push(new Node(2));
        linkedStack.push(new Node(3));
        linkedStack.push(new Node(4));
        linkedStack.push(new Node(5));
        System.out.printf("当前的大小为:%d\n", linkedStack.getSize());
        linkedStack.list();
        System.out.println("取出顶的数据后:");
        linkedStack.pop();
        linkedStack.list();

    }
}

// 链表实现,单链表从头部插入数据删除数据
class LinkedStack{
    private Node head; // 头结点
    private int size; // 的大小

    // 构造
    public void LinkedStack(){
        this.size = -1;
        this.head = null;
    }

    // 是否为空
    public boolean isEmpty(){
        return size < 0;
    }

    // 获取链表长度
    public int getSize(){
        return size;
    }


    // 插入数据
    public void push(Node node){
        if (head == null) { // 如果头结点为空,链表没有数据,node 赋值给 head 节点
            head = node;
        } else {
            node.next = head; // 头结点作为插入节点的下一个节点
            head = node; // 插入节点成为头结点
        }
        size ++; // 链表长度增加
    }

    // pop 取出数据
    public Object pop(){
        if (head == null) {
            System.out.println("链表内没有数据");
        }
        if (head.next == null) { // 头结点下一个节点是否为空,取出头结点
            head = null; // 将头结点赋值为 null
            size --; // 链表长度 -1
            return head.data;
        } else {
            head = head.next; // 头结点的下一个节点赋值给头节点
            size --; // 链表长度减一
            return head.data;
        }
    }

    // 打印内所有数据
    public void list() {
        if (isEmpty()) { // 判断是否为空
            System.out.println("内没有数据~");
            return;
        }
        Node temp = head;
        while (true) { // 循环打印
            if (temp == null) { // 内没有数据
                break;
            }
            System.out.printf("%d\n", temp.data);
            temp = temp.next; // temp 等于下一个节点
        }
    }

}

// 链表节点 Node
class Node{
    public Object data; // 节点数据
    public Node next; // 下一个节点

    public Node(Object data) {
        this.data = data;
    }

}

http://www.niftyadmin.cn/n/818328.html

相关文章

算法复杂度速查表

来源&#xff1a;始终 liam.page/2016/06/20/big-O-cheat-sheet/ 复杂度通常会使用大-O 记号来表示&#xff0c;比如快速排序的平均时间复杂度是 O(nlog(n))。虽然我是「理解派」&#xff0c;但是虽然每个算法/数据结构都理解了&#xff0c;不时仍有可能忘记具体某个算法/数据结…

漫谈程序员系列:让程序员蛋疼的那些事儿

听说嫁人要嫁程序员&#xff0c;钱多话少死得早。这话多半是程序员自己黑自己的。程序员是有非常特别的幽默感的一群&#xff0c;善于自嘲&#xff0c;勇于自黑&#xff0c;耐受力超强&#xff0c;很多事无可无不可&#xff0c;不到是不可孰不可忍不会冲冠一怒。不过&#xff0…

模块 - random/string/os/sys/shutil/zipfile/tarfile

random 模块 方法&#xff1a; >>> random.randint(1,3) #会包含 1 2 3 3 >>> random.randrange(1,3) #会包含 1 2 不包含 3 2 >>> random.randrange(1,6,2) #只出现 1 3 5 5 >>> random.random() #[0…

Qt Quick里的图形效果:阴影(Drop Shadow)

Qt Quick提供了两种阴影效果&#xff1a;DropShow&#xff0c;阴影。这个元素会根据源图像&#xff0c;产生一个彩色的、模糊的新图像&#xff0c;把这个新图像放在源图像后面&#xff0c;给人一种源图像从背景上凸出来的效果。InnerShadow&#xff0c;内阴影。这个元素会根据源…

浅析 VO、DTO、DO、PO 的概念、区别和用处!

目录概念&#xff1a;模型&#xff1a;VO与DTO的区别VO与DTO的应用DTO与DO的区别DTO与DO的应用DO与PO的区别DO与PO的应用本篇文章主要讨论一下我们经常会用到的一些对象&#xff1a;VO、DTO、DO和PO。 由于不同的项目和开发人员有不同的命名习惯&#xff0c;这里我首先对上述的…

Android studio动态调试

Reference: http://cstsinghua.github.io/2016/06/13/Android%20studio%E5%8A%A8%E6%80%81%E8%B0%83%E8%AF%95%E6%8C%87%E5%8D%97/#anchor 首先&#xff0c;请先下载apktool工具并熟悉其命令的使用&#xff0c;可参见其官网说明https://ibotpeaches.github.io/Apktool/install…

漫谈程序员系列:神奇的四步编程法

我曾经学习过很多门开发语言&#xff0c;C、C、Java、Lua、JavaScript、Python、Scala、Pascal等&#xff0c;不断地从零开始学习新语言&#xff0c;强化了我对学习过程的记忆&#xff0c;使得我对如何学习编程语言积累了一点点心得&#xff0c;我一直想把它记录下来&#xff0…

Kafka 学习(一)Kafka 简介

1、kafka概述 1.1 定义 kafka是一个高吞吐量的 分布式 发布订阅消息系统&#xff0c;分布式的基于 发布 订阅模式的消息队列 &#xff08;Message Queue&#xff09;MQ&#xff0c;主要应用于大数据实时处理方面Kafka 对于消息保存时根据 Topic 进行归类&#xff0c;发送消息…