• 学习数据结构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);
                }
            }
        }
    }
    
  • 相关阅读:
    WPF之SharpAvi视频录制(AVI)
    WPF之录制桌面视频(FFMPeg)
    Unity3d之Navigation导航系统(AII敌人)
    Unity3D之InstantOC(遮挡剔除)
    Unity3D之Camera
    Unity3D之Material(材质、着色器、纹理)
    分布式服务弹性框架“Hystrix”实践与源码研究(一)
    平安某金所奇葩的面经-关于幂等和ROA设计的反思
    来自GitHub的Android UI开源项目
    JavaScript实现MVVM之我就是想监测一个普通对象的变化
  • 原文地址:https://www.cnblogs.com/xiaobaoa/p/11941642.html
Copyright © 2020-2023  润新知