美文网首页
数据结构——栈和队列

数据结构——栈和队列

作者: yaco | 来源:发表于2020-03-27 13:03 被阅读0次
  • 用数组实现栈和队列
  • 用栈实现队列
  • 用队列实现栈
  • 栈和队列的经典算法题
    • 最小间距栈
    • 宠物收养所

数组实现栈和队列

  1. 用数组实现栈:
    • 创建一个类,包含一个数组和当前栈中存在的记录总数
    • arr用于记录入栈元素, size记录当前的栈长度
      代码如下:
    // 用数组实现栈,实现增,删,查功能
    static class ArrayStack{
        int[] arr;
        int size;

        public ArrayStack(int capacity) {
            this.arr = new int[capacity];
            this.size = 0;
        }

        // 检查是否栈空
        public boolean isEmpty() {
            return this.size == 0;
        }

        // 检查是否栈满
        public boolean isFull() {
            return this.size == this.arr.length;
        }

        // 向栈中添加元素
        public void push(int num) {
            if (isFull()) {
                throw new RuntimeException("stack is full");
            }
            arr[this.size++] = num;
        }

        // 从栈中弹出元素
        public int pop() {
            if (isEmpty()) {
                throw new RuntimeException("stack is null");
            }
            return arr[--size];
        }

        // 查看栈顶元素
        public int peek() {
            if (isEmpty()) {
                throw new RuntimeException("stack is null");
            }
            return arr[size - 1];
        }
        
        // 检查当前栈的大小
        public int size(){
            return this.size;
        }

        // toString()
        @Override
        public String toString() {
            return "ArrayStack{" +
                    "arr=" + Arrays.toString(arr) +
                    ", size=" + size +
                    '}';
        }
  1. 用数组实现队列
    • arr数组: 用于存放每次进入队列的元素
    • size: 当前队列的存量
    • start: 头指针,用于取出元素
    • end:尾指针,用于添加元素
class ArrayQueue{
    private Integer[] arr;
    private Integer start;
    private Integer end;
    private Integer size;

    public void ArrayStack(int initSize) {
        if(initSize < 0) {
            throw new IllegalArgumentException("The size is less on 0");
        }
        arr = new Integer[initSize];
        start = 0;
        end = 0;
        size = 0;
    }

    // 入队列
    public void push(Integer obj) {
        if(isFull()) {
            throw new ArrayIndexOutOfBoundsException("The queue is full!");
        }
        arr[end] = obj;
        end = arr.length == end + 1 ? 0 : end + 1;
        size++;
    }

    // 出队列
    public Integer poll() {
        if(isEmpty()) {
            throw new ArrayIndexOutOfBoundsException("The queue is empty!");
        }
        size--;
        int temp = arr[start];
        start = arr.length == start + 1 ? 0 : start + 1;
        return temp;
    }

    // 弹出队列头
    public Integer peek() {
        if(isEmpty()) {
            throw new ArrayIndexOutOfBoundsException("The queue is empty!");
        }
        return arr[start];
    }

    // 检测队列是否为空
    public boolean isEmpty(){
        return size == 0;
    }

    // 检查队列是否已满
    public boolean isFull() {
        return size == arr.length;
    }

栈实现队列

  1. 基本思路:(面试常考题))——leeCode232题
    • 双栈实现队列(stack1 简称s1, stack2 简称s2)
    • 添加元素时,只需要不停的向s1中添加元素即可
    • 弹出队列头时,首先检测s2是否为空,如果为空,则把s1整体弹出压入s2,从而颠倒了入栈顺序,然后依次进行弹出即可
    class MyQueue {
        Stack<Integer> s1;
        Stack<Integer> s2;

        /** Initialize your data structure here. */
        public MyQueue() {
            s1 = new Stack<>();
            s2 = new Stack<>();
        }

        /** Push element x to the back of queue. */
        public void push(int x) {
            s1.push(x);
        }

        /** Removes the element from in front of queue and returns that element. */
        public int pop() {
            if (empty()) {
                throw new RuntimeException("The queue is empty");
            }
            if (s2.isEmpty()) {
                while (!s1.isEmpty()) {
                    s2.push(s1.pop());
                }
            }
            return s2.pop();
        }

        /** Get the front element. */
        public int peek() {
            if (empty()) {
                throw new RuntimeException("The queue is empty");
            }
            if (s2.isEmpty()) {
                while (!s1.isEmpty()) {
                    s2.push(s1.pop());
                }
            }
            return s2.peek();
        }

        /** Returns whether the queue is empty. */
        public boolean empty() {
            return s1.isEmpty() && s2.isEmpty();
        }
    }

队列实现栈

面试题 ———— leeCode225

  • 创建两个队列q1和q2;
  • 添加元素时,直接向q1里面扔
  • 弹出元素时,首先将q1队列里面的元素依次出队列进入q2,直到q1里面只剩下一个元素,则将子元素弹出,然后q1和q1互换指引即可。
class MyStack {
    Queue<Integer> q1;
    Queue<Integer> q2;


    /** Initialize your data structure here. */
    public MyStack() {
        q1 = new LinkedList<>();
        q2 = new LinkedList<>();
    }

    /** Push element x onto stack. */
    public void push(int x) {
        q1.add(x);
    }

    /** Removes the element on top of the stack and returns that element. */
    public int pop() {
        if (empty()) {
            throw new RuntimeException("The stack is empty");
        }
        while (q1.size() != 1) {
            q2.add(q1.poll());
        }
        int ans = q1.poll();
        swap();
        return ans;        
    }

    /** Get the top element. */
    public int top() {
        if (empty()) {
            throw new RuntimeException("The stack is empty");
        }
        while (q1.size() != 1) {
            q2.add(q1.poll());
        }
        int ans = q1.peek();
        q2.add(q1.poll());
        swap();
        return ans;
    }

    /** Returns whether the stack is empty. */
    public boolean empty() {
        return q1.isEmpty();
    }
    
    /**Exchange q1 and q2.**/
    public void swap() {
        Queue<Integer> temp = new LinkedList<>();
        temp = q1;
        q1 = q2;
        q2 = temp;
    }
}

队列和栈的应用

(leeCode155——最小栈 —— easy)
一、 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。
要求:
1. pop\push\getMin操作的时间复杂度都是O(1)
2. 设计的栈可以使用现成的栈结构

基本思路:

  • 创建两个栈(dataStack)存放数据, minStack(存放当前的最小值)
  • push数据时,dataStack直接入栈,对于minStack, 如果栈空,或者当前的栈顶元素大于等于入栈元素,则minStack也入栈
  • pop数据时,dataStack正常pop, minStack栈顶元素如果和当前pop的元素相等的时候,则minStack也需要pop
  • 具体代码如下
    class MinStack {
        Stack<Integer> dataStack;   // 存放数据的栈
        Stack<Integer> minStack;    // 存放当前最小值的栈

        public MinStack() {
            dataStack = new Stack<Integer>();
            minStack = new Stack<Integer>();
        }

        // 数据入栈
        public void push(int x) {
            // 如果min栈空,直接入栈,否则比较大小,若小于等于,则入栈
            if(minStack.isEmpty() || x <= minStack.peek()){
                minStack.push(x);
            }
            dataStack.push(x);
        }

        // 数据出栈
        public int pop(){
            if(empty()){
                throw new RuntimeException("The stack is empty");
            }
            // 如果当前dataStack栈顶元素和minStack栈顶元素相同,则同时出栈
            int cur = dataStack.pop();
            if(cur == minStack.peek()){
                minStack.pop();
            }
            return cur;
        }

        // 获取当前的最小值
        public int getMin() {
            if(minStack.isEmpty()){
                throw new RuntimeException("The stack is empty");
            }
            return minStack.peek();
        }

        // 判空
        public boolean empty(){
            return dataStack.isEmpty();
        }
    }

二、 宠物收养所(又名猫狗队列) ————lintCode230(hard)

在一个宠物避难所里,仅有狗和猫两种动物可供领养,且领养时严格执行“先进先出”的规则。
如果有人想要从避难所领养动物,他只有两种选择:要么选择领养所有动物中最资深的一只(根据到达避难所的时间,越早到的越资深),要么选择领养猫或狗(同样,也只能领养最资深的一只)。也就是说,领养者不能随意选择某一指定动物。请建立一个数据结构,使得它可以运行以上规则,并可实现 enqueue, dequeueAny, dequeueDog, 和 dequeueCat 操作。
解释:
enqueue: 猫或者狗入队列
dequeueAny: 按照添加的顺序出队列,不考虑猫狗属性
dequeueDog: 领养狗,弹出最后入队列的狗
dequeueCat: 领养猫,弹出最后入队列的猫

基本思路: 宠物队列由猫队列和狗队列组成,按照宠物属性分别加进不同的队列中,然后每次加入时都给宠物设置一个编号,编号越小,加入时间越早

    // 创建宠物类
    class Pet{
        private String type;

        // 构造器
        public Pet(String type){
            this.type = type;
        }

        public String getType() {
            return type;
        }
    }

    // 创建猫类
    class Cat extends Pet{
        public Cat() {
            super("cat");
        }
    }

    // 创建狗类
    class Dog extends Pet{
        public Dog() {
            super("dog");
        }
    }

    // 创建添加进入队列的对象
    class EnterPet{
        private Pet pet;    // 入队列的对象
        private long count;  // 入队列对象的编号(编号越小,越早进入队列)

        public EnterPet(Pet pet, long count) {
            this.pet = pet;
            this.count = count;
        }

        public Pet getPet() {
            return pet;
        }

        public void setPet(Pet pet) {
            this.pet = pet;
        }

        public long getCount() {
            return count;
        }

        public void setCount(long count) {
            this.count = count;
        }
    }

    // 创建动物队列
    class AnimalsQueue{
        private Queue<EnterPet> catQueue;   // 猫队列
        private Queue<EnterPet> dogQueue;   // 狗队列
        private long count;                 // 记录队列总共接收的宠物总数

        // 构造器
        public AnimalsQueue(){
            this.catQueue = new LinkedList<EnterPet>();
            this.dogQueue = new LinkedList<EnterPet>();
            this.count = 0;
        }

        // 宠物入队列
        public void enQueue(Pet pet) {
            if(pet.getType().equals("cat")){
                catQueue.add(new EnterPet(pet,count++));
            }else if(pet.getType().equals("dog")){
                dogQueue.add(new EnterPet(pet,count++));
            }else{
                throw new RuntimeException("not dog or cat");
            }
        }

        // 根据添加顺序出队列
        public Pet deQueueAny(){
            Pet pet = null;
            // 猫狗队列都不为空
            if(!dogQueue.isEmpty() && !catQueue.isEmpty()){
                if(dogQueue.peek().getCount() < catQueue.peek().getCount()){
                    pet = dogQueue.poll().getPet();
                }else{
                    pet = catQueue.poll().getPet();
                }
            }else if(!catQueue.isEmpty()){
                pet = catQueue.poll().getPet();
            }else if(!dogQueue.isEmpty()){
                pet = dogQueue.poll().getPet();
            }else{
                throw new RuntimeException("Queue is empty");
            }
            return pet;
        }
        
        // 猫出队列
        public Pet deQueueCat(){
            if(catQueue.isEmpty()){
                throw new RuntimeException("catQueue is empty");
            }
            return catQueue.poll().getPet();
        }
        
        // 狗出队列
        public Pet deQueueDog(){
            if(dogQueue.isEmpty()){
                throw new RuntimeException("dogQueue is empty");
            }
            return dogQueue.poll().getPet();
        }
        
        // 查看是否还有宠物
        public boolean isEmptyAll() {
            return catQueue.isEmpty() && dogQueue.isEmpty();
        }
        
        // 查看是否还有猫
        public boolean isEmptyCat() {
            return catQueue.isEmpty();
        }

        // 查看是否还有狗
        public boolean isEmptyDog() {
            return dogQueue.isEmpty();
        }
    }+

相关文章

  • Algorithm小白入门 -- 队列和栈

    队列和栈队列实现栈、栈实现队列单调栈单调队列运用栈去重 1. 队列实现栈、栈实现队列 队列是一种先进先出的数据结构...

  • 栈和队列—什么是栈

    栈和队列是两种重要的数据结构 从数据结构角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表操作的子...

  • 栈和队列—什么是队列

    栈和队列是两种重要的数据结构 从数据结构角度看,栈和队列也是线性表,其特殊性在于栈和队列的基本操作是线性表操作的子...

  • 队列和栈的应用

    队列和栈的使用 标签(空格分隔): algorithm 队列和栈的应用 1.队列的应用 队列是一种常见的数据结构,...

  • 泡杯茶,我们坐下聊聊javascript事件环

    栈和队列 在计算机内存中存取数据,基本的数据结构分为栈和队列。 栈(Stack)是一种后进先出的数据结构,注意,有...

  • 算法导论 基本数据结构

    MIT公开课没有讲到的内容,介绍几种基本数据结构- 栈和队列- 链表- 二叉树 栈和队列 栈和队列都是动态集合,元...

  • 栈、队列和链表

    基本数据结构 栈和队列 栈和队列都是动态集合。栈实现的是一种后进先出策略。队列是一种先进先出策略。 栈 栈上的in...

  • 数据结构:栈和队列

    栈和队列 栈和队列是软件设计中常用的两种数据结构,逻辑结构和线性表相同。 特点: 栈: "先进后出"队列:"先进先...

  • 数据结构 栈和队列

    数据结构 栈和队列 栈 顺序栈 top = -1 链栈 初始化 判断队空 入队: 头插法 出队: 单链表删除 队列...

  • 第四章栈与队列

    知识大纲 栈和队列的数据结构 相同点 栈和队列都是对删除和插入做了限制的线性表 栈和队列的都是建立在线性表的...

网友评论

      本文标题:数据结构——栈和队列

      本文链接:https://www.haomeiwen.com/subject/skghuhtx.html