• 学习数据结构Day3


    栈和队列

    • 栈是一种线性结构,相比数组
    • 他对应的操作是数组的子集
    • 只能从一端进入,也只能从一端取出
    • 这一端成为栈顶

    栈是一种先进后出的数据结构,Last In First Out(LIFO)

    • 程序调用的系统栈
    • 栈的应用:无处不在的Undo操作(撤销)

    栈的实现

    Stack<E>

    • void push(E)
    • E pop()
    • E peek()
    • int getSize()
    • boolean isEmpty()

    将自己写的栈设置为接口,然后用第一天的动态数组实现这个接口。因为有了上一个自己做的动态数组,所以栈的形

    成是非常方便的。

    public class ArrayStack<E> implements Stack<E> {
    
        DynamicArray<E> array;
    
        public ArrayStack(int capacity){
            array = new DynamicArray<E>(capacity);
        }
    
        public ArrayStack(){
            array = new DynamicArray<E>();
        }
    
        @Override
        public int getSize() {
            return array.getSize();
        }
    
        @Override
        public void push(E e) {
            array.addLast(e);
        }
    
        @Override
        public boolean isEmpty() {
            return array.isEmpty();
        }
    
        @Override
        public E pop() {
            return array.removeLast();
        }
    
        @Override
        public E peek() {
            return array.getLast();
        }
    
        public int getCapacity(){
            return array.capacity();
        }
    
        @Override
        public String toString(){
            StringBuilder builder = new StringBuilder();
            builder.append("stack:");
            builder.append("[");
            for (int i = 0; i < array.getSize(); i++) {
                builder.append(array.get(i));
                if(i != array.getSize()-1){
                    builder.append(", ");
                }
            }
            builder.append("] top");
            return builder.toString();
        }
    

    时间复杂度都是O(1),其中,push和pop都是均摊为O(1)

    队列

    队列也是一个线性结构,有队首和队尾。先进先出。我们自己去编写一个队列。要实现以下方法

    • void enqueue(E)
    • E dequeue()
    • E getFront()
    • int getSize()
    • boolean isEmpty()
    
    public interface Queue<E> {
        int getSize();
        boolean isEmpty();
        void enqueue(E e);
        E dequeue();
        E getFront();
    }
    
    public class ArrayQueue<E> implements Queue<E>{
    
        private DynamicArray array;
    
        public ArrayQueue(int capacity) {
            array = new DynamicArray<>(capacity);
        }
    
        public ArrayQueue() {
            array = new DynamicArray();
        }
    
        @Override
        public int getSize() {
            return array.getSize();
        }
    
        @Override
        public boolean isEmpty() {
            return array.isEmpty();
        }
    
        @Override
        public void enqueue(E e) {
            array.addLast(e);
        }
    
        public int getCapacity(){
            return array.capacity();
        }
    
        @Override
        public E dequeue() {
            return (E) array.removeFirst();
        }
    
        @Override
        public E getFront() {
            return null;
        }
    
        @Override
        public String toString(){
            StringBuilder builder = new StringBuilder();
            builder.append("Queue:");
            builder.append("front [");
            for (int i = 0; i < array.getSize(); i++) {
                builder.append(array.get(i));
                if(i != array.getSize()-1){
                    builder.append(", ");
                }
            }
            builder.append("]");
            return builder.toString();
        }
    }
    

    写完这个队列我们发现,这个队列,出队列的时间复杂度是O(n),严重的影响了运算效率,所以我们利用指针,指出

    首尾指针,所以维护指针就可以了。所以,基于这样的想法,我们就想出了循环队列的队列。

    front == tail 队列为空

    ( tail +1 )% c== front 队列满

    在capacity中,浪费了一个空间。

    package Queue;
    
    
    
    /**
     * @author shkstart
     * @create 2019-11-25 20:05
     */
    public class LoopQueue<E> implements Queue<E> {
    
        private E[] data;
    
        private int front, tail;
    
        private int size;
    
        public LoopQueue(int capacity) {
            data = (E[]) new Object[capacity + 1];
            front = 0;
            tail = 0;
            size = 0;
        }
    
        public LoopQueue() {
            this(10);
        }
    
        public int getCapacity() {
            return data.length - 1;
        }
    
        @Override
        public int getSize() {
            return size;
        }
    
        /**
         * 判断是否为空的条件
         *
         * @return
         */
        @Override
        public boolean isEmpty() {
            return tail == front;
        }
    
        /**
         * 如队列的操作!一定不要忘了循环队列维护
         *
         * @param e
         */
        @Override
        public void enqueue(E e) {
            if ((tail + 1) % data.length == front) {//队列满
                resize(getCapacity() * 2);
            }
    
            data[tail] = e;
            tail = (tail + 1) % data.length;
            size++;
        }
    
        private void resize(int newCapacity) {
            E[] newdata = (E[]) new Object[newCapacity];
            for (int i = 0; i < size; i++) {
                newdata[i] = data[(front + i) % data.length];
    
                data = newdata;
                front = 0;
                tail = size;
            }
        }
    
        @Override
        public E dequeue() {
    
            if (isEmpty()) {
                throw new IllegalArgumentException("Cannot dequeue from an empty queue");
            }
            E ret = data[front];
            data[front] = null;
            front = (front + 1) % data.length;
            size--;
            if (size == getCapacity() / 4 && getCapacity() / 2 != 0) {
                resize(getCapacity() / 2);
            }
            return ret;
        }
    
        @Override
        public E getFront() {
            if (isEmpty()) {
                throw new IllegalArgumentException("Cannot dequeue from an empty queue");
            }
            return data[front];
        }
    @Override
    public String toString() {
    StringBuilder res = new StringBuilder();
    res.append(String.format("Queue: size = %d , capacity = %d
    ", size, getCapacity()));
    res.append("front [");
    for(int i = front ; i != tail ; i = (i + 1) % data.length){
    res.append(data[i]);
    if((i + 1) % data.length != tail)
    res.append(", ");
            }
    res.append("] tail");
    return res.toString();
        }
    public static void main(String[] args) {
    LoopQueue<Integer> arrayQueue = new LoopQueue<Integer>();
    for (int i = 0; i < 10; i++) {
    arrayQueue.enqueue(i);
    System.out.println(arrayQueue);
    if(i % 3 == 2){
    arrayQueue.dequeue();
    System.out.println(arrayQueue);
                }
            }
        }
    }
    
  • 相关阅读:
    HDU2586 How far away?(tarjan的LCA)
    You Raise Me Up
    POJ2891 Strange Way to Express Integers(中国剩余定理)
    POJ2142 The Balance(扩展欧几里得)
    HDU 1166模仿大牛写的线段树
    NetWord Dinic
    HDU 1754 线段树裸题
    hdu1394 Minimum Inversion Number
    hdu2795 Billboard
    【完全版】线段树
  • 原文地址:https://www.cnblogs.com/xiaobaoa/p/11941642.html
Copyright © 2020-2023  润新知