• 数据结构-栈


    栈与队列

    image-20200702231902564

    概念

    栈:是限定仅在表尾进行插入和删除操作的线性表

    栈顶(top):允许插入和删除的一端,即表尾称为栈顶

    栈底(bottom):表头称为栈底

    栈是LIFO结构,后进先出。

    与线性表相比,特殊之处在于

    限制了线性表的插入和删除位置,始终在栈顶进行。

    所以栈底是固定的,最先进栈的只能在栈底

    相关操作

    栈的插入操作 —> 进栈(圧栈、入栈)

    栈的删除操作 —> 出栈(弹栈)

    假设入栈元素从小到大,出栈的每个元素后面比该元素小的元素,应该按从大到小的相对顺序排列

    比如数字元素1、2、3依次进栈,

    出栈顺序可能是 1、2、3 / 1、3、2 / 2、1、3 / 2、3、1 / 3、2、1

    不可能是 3、1、2 的出栈顺序。

    抽象数据类型

    image-20200703234724462

    栈的顺序存储结构

    用数组实现

    ArrayStack.java

    package com.stack;
    
    /**
     * 用数组实现的顺序表
     * 限制操作端,使其成为栈
     */
    public class ArrayStack {
    
        private int maxSize;
        private int[] stack;
        private int top = -1;
    
        public ArrayStackDemo(int maxSize) {
            this.maxSize = maxSize;
            stack = new int[maxSize];
        }
    
        public boolean isFull() {
            return top == maxSize - 1;
        }
    
        public boolean isEmpty() {
            return top == -1;
        }
    
    
        public void push(int value) {
            // 入栈
            if (isFull()) {
                System.out.println("栈满了");
                return;
            }
    
            stack[++top] = value;
        }
    
        public int pop() {
            // 出栈
            if (isEmpty()) {
                throw new RuntimeException("栈空");
            }
            return stack[top--];
        }
    
        public void list() {
            if (isEmpty()) {
                System.out.println("没有数据");
                return;
            }
            for (int i = top; i >= 0; i--) {
                System.out.printf("stack[%d]=%d
    ",i,stack[i]);
            }
        }
    }
    

    栈的链式存储结构

    简称链栈

    LinkStack.java

    package com.stack;
    
    /**
     * 因为头结点是必须的,栈顶指针也是必须的。
     * 所以合二为一!即初始化的时候不需要头结点
     */
    public class LinkStack {
        private Node top;
    
        public boolean isFull() {
            return false;
        }
    
        public boolean isEmpty() {
            return top == null;
        }
    
    
        public void push(int num) {
            // 很少满栈,直接创建结点头插
            Node node = new Node(num);
            node.next = top;
            top = node;
        }
    
        public int pop() {
            // 出栈
            if (isEmpty()) {
                throw new RuntimeException("栈空");
            }
            int value = top.data;
            top = top.next;
            return value;
        }
    
        public void list() {
            if (isEmpty()) {
                System.out.println("没有数据");
                return;
            }
            Node temp = top;
            while (temp != null) {
                System.out.print(temp.data+"	");
                temp = temp.next;
            }
        }
    
    }
    
    class Node{
        public int data;
        public Node next;
    
        public Node() {
        }
    
        Node(int data) {
            this.data = data;
        }
    }
    

    Java中自带封装好的Stack类,可以直接使用。

    image-20200705220627953

    底层继承关系 class Stack<E> extends Vector<E>

    用数组存储,如果栈满会自动扩容。

    对比

    顺序栈与链栈,它们在时间复杂度上是一样的,均为0(1)。

    对于空间性能,顺序栈需要事先确定一个固定的长度,可能会存在内存空间浪费的问题,

    但它的优势是存取时定位很方便,

    而链栈则要求每个元素都有指针域,这同时也增加了一些内存开销,但对于栈的长度无限制。

    所以它们的区别和线性表中讨论的一样,如果栈的使用过程中元素变化不可预料,有时很小,

    有时非常大,那么最好是用链栈,反之,如果它的变化在可控范围内,建议使用顺序栈会更好一些。

    栈的作用

    • 递归
    • 逆波兰式
    • 中缀转后缀
  • 相关阅读:
    堆与堆排序
    利用openssl进行RSA加密解密
    [转载]编辑器圣战
    七月底的小结
    计算机是怎么样工作的?
    Linux进程地址空间之初探:一
    微软2013暑期实习笔试回忆
    微软编程之美资格赛
    微软编程之美初赛
    rootkit:实现隐藏进程
  • 原文地址:https://www.cnblogs.com/1101-/p/13252544.html
Copyright © 2020-2023  润新知