学习数据结构Day3

时间:2019-11-27
本文章向大家介绍学习数据结构Day3,主要包括学习数据结构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\n", 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);
            }
        }
    }
}

原文地址:https://www.cnblogs.com/xiaobaoa/p/11941642.html