数据结构——栈和队列

  • 用数组实现栈和队列
  • 用栈实现队列
  • 用队列实现栈
  • 栈和队列的经典算法题
    • 最小间距栈
    • 宠物收养所

数组实现栈和队列

  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 s1;
        Stack 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 q1;
    Queue 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 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 dataStack;   // 存放数据的栈
        Stack minStack;    // 存放当前最小值的栈

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

        // 数据入栈
        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 catQueue;   // 猫队列
        private Queue dogQueue;   // 狗队列
        private long count;                 // 记录队列总共接收的宠物总数

        // 构造器
        public AnimalsQueue(){
            this.catQueue = new LinkedList();
            this.dogQueue = new LinkedList();
            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();
        }
    }+

你可能感兴趣的:(数据结构——栈和队列)