数据结构与算法(二) 栈与队列(代码示例)

1. 数组和链表实现栈

链表的方式:

/**
 * 描述:栈的链表实现
 *
 * @author Ye
 * @version 1.0
 * @date 2021/8/20 13:44
 */
public class Stack<E> {
    Node1<E> top = null;
    public boolean isEmpty(){
        return top == null;
    }

    public void push(E data){
        Node1<E> newLen = new Node1<>(data);
        newLen.next = top;
        top = newLen;
    }

    public E pop(){
        if (this.isEmpty()){
            return null;
        }
        E data = top.data;
        top = top.next;
        return data;
    }

    public E peek(){
        if (isEmpty()){
            return null;
        }
        return top.data;
    }

}

class Node1<E>{
    Node1<E> next = null;
    E data;
    public Node1(E data){
        this.data = data;
    }
}

数组的方式:

import java.util.Arrays;

/**
 * 描述:栈的数组实现
 *
 * @author Ye
 * @version 1.0
 * @date 2021/8/20 13:07
 */
public class MyStack<E> {
    private Object[] stack;

    /**
     * 数组中存储元素个数
     */
    private int size;

    public MyStack(){
        /**
         * 初始长度为10
         */
        stack = new Object[10];
}

    /**
     * 判断堆栈是否为空
     */
    public boolean isEmpty(){
        return size == 0;
    }

    public E peek(){
        if (isEmpty()){
            return null;
        }
        return (E)stack[size - 1];
    }

    public E pop(){
        E e = peek();
        stack[size - 1] = null;
        size --;
        return e;
    }

    public E push(E item){
        /**
         * 检查容量
         */
        ensureCapacity(size + 1);
        stack[size++] = item;
        return item;
    }

    /**
     * 判断数组器是否已满,若已满,则扩充数组空间
     */
    private void ensureCapacity(int size){
        int len = stack.length;
        /**
         * 数组已满
         */
        if (size > len){
            /**
             * 每次数组扩充的容量
             */
            int newLen = 10;
            stack = Arrays.copyOf(stack,newLen);
        }
    }

    public static void main(String[] args) {
        MyStack<Integer> s = new MyStack<>();
        s.push(1);
        s.push(6);
        s.push(10);
        System.out.println("栈中的元素个数: " + s.size);
        System.out.println("栈顶元素为: " + s.pop());
        System.out.println("栈顶元素为: " + s.pop());
    }
}

运行截图:
在这里插入图片描述

2. 用O(1)的时间复杂度求栈中的最小元素

只用O(1)就找出最小值,说明不能遍历栈;而只用O(1)那么短的时间,一般是牺牲了空间来换取的。
所以设计的思路就是,用另一个栈来记录最小值。具体实现如下
代码如下:

package com.example.demo;

/**
 * 描述:用O(1)的时间复杂度求栈中的最小元素
 *
 * @author Ye
 * @version 1.0
 * @date 2021/8/20 14:23
 */
public class MyStack1 {
    MyStack<Integer> elem;
    MyStack<Integer> min;
    public MyStack1(){
        elem = new MyStack<>();
        min = new MyStack<>();
    }

    public void push(int data){
        elem.push(data);
        if (min.isEmpty()){
            min.push(data);
        }else {
            if (data < min.peek()){
                min.push(data);
            }
        }
    }

    public int pop(){
        int topData = elem.peek();
        elem.pop();
        if (topData == this.min()){
            elem.pop();
        }
        return topData;
    }

    public int min(){
        if (min.isEmpty()){
            return Integer.MIN_VALUE;
        }else {
            return min.peek();
        }
    }
}

3. 链表和数组实现队列

链表的实现:

/**
 * 描述:链表实现队列
 *
 * @author Ye
 * @version 1.0
 * @date 2021/8/20 14:51
 */

public class MyQueue<E>{

    private Node2<E> head = null;
        private Node2<E> tail = null;
        public boolean isEmpty(){
            return head == tail;
        }
        public void put(E data){
            Node2<E> newNode = new Node2<>(data);
            // 队列为空
            if (head == null && tail == null){
                head = tail = newNode;
            }else {
                tail.next = newNode;
                tail = newNode;
            }

        }

        public E pop(){
            if (this.isEmpty()){
                return null;
            }
            E data = head.data;
            head = head.next;
            return data;
        }

        public int size(){
            Node2<E> temp = head;
            int n = 0;
            while (temp != null){
                n++;
                temp = temp.next;
            }
            return n;
        }

        public static void main(String[] args) {
            MyQueue<Integer> queue = new MyQueue<Integer>();
            queue.put(56);
            queue.put(6);
            queue.put(163);
            System.out.println("队列长队为: " + queue.size());
            System.out.println("队列首元素: " + queue.pop());
            System.out.println("队列首元素: " + queue.pop());
        }
}


class Node2<E> {
    Node2<E> next = null;
    E data;

    public Node2(E data) {
        this.data = data;
    }
}

运行截图:
在这里插入图片描述
数组的实现:
为了实现多线程的安全,增加了对队列操作的同步

import java.util.LinkedList;

/**
 * 描述:数组实现队列
 *
 * @author Ye
 * @version 1.0
 * @date 2021/8/27 19:49
 */
public class MyQueue1<E> {
    private LinkedList<E> list = new LinkedList<>();
    private int size = 0;
    public synchronized void put(E e){
        list.addLast(e);
        size++;
    }

    public synchronized E pop(){
        size--;
        return list.removeFirst();
    }

    public synchronized boolean empty(){
        return size == 0;
    }

    public synchronized int size(){
        return size;
    }
}

4. 用两个栈模拟队列操作

使用栈A与栈B模拟队列Q,s1为插入栈,s2为弹出栈。
具体实现如下,使用Java内置的Stack来实现:

import java.util.Stack;

/**
 * 描述:两个栈实现队列
 *
 * @author Ye
 * @version 1.0
 * @date 2021/9/12 20:16
 */
public class MyQueue2<E> {
    private Stack<E> s1 = new Stack<>();
    private Stack<E> s2 = new Stack<>();
    public synchronized void put(E e){
        s1.push(e);
    }
    public synchronized E pop(){
        if (s2.isEmpty()){
            while (!s1.isEmpty()){
                s2.push(s1.pop());
            }
        }
        return s2.pop();
    }
    public synchronized boolean empty(){
        return s1.isEmpty() && s2.isEmpty();
    }
    public static void main(String[] args){
        MyQueue<Integer> q = new MyQueue<>();
        q.put(1);
        q.put(5);
        q.put(53);
        System.out.println("队列首元素:" + q.pop());
        System.out.println("队列首元素:" + q.pop());
    }
}

运行截图:
在这里插入图片描述

参考:《Java程序员面试笔试宝典》 何昊、薛鹏、叶向阳 编著

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值