数组队列

数组队列

1、队列相关概念

  • 队列是一种线性结构
  • 相比数组,队列的操作是数组的子集
  • 只能从一端(队尾)添加元素,只能从另一端(队首)取出元素

 

2、队列原理

       队列是一种先进先出的数据结构(先到先得)

       Fist In First Out(FIFO)

  

       队首取出元素,队尾添加元素。

 

3、队列实现

(1)队列需要实现的方法

(2)底层使用数组实现队列

 

(3)编码实现队列

     Queue接口定义:

public interface Queue<E> {

    // 入队

    void enqueue(E e);



    // 出队

    E dequeue();



    // 获取队首元素

    E getFront();



    // 获取队列大小

    int getSize();



    // 判断队列是否为空

    boolean isEmpty();



}

动态数组Array定义:

public class Array<E> {

    // 定义数组变量,data.length表示数组容量capacity

    private E[] data;

    // 定义数组中存放数据大小

    private int size;



    // 有参构造方法,传入数组的容量capacity构造动态数组

    public Array(int capacity) {

        data = (E[]) new Object[capacity];

        size = 0;

    }



    // 无参构造方法,默认初始容量为capacity=10

    public Array() {

        this(10);

    }



    // 获取数组中元素个数

    public int getSize() {

        return size;

    }



    // 获取数组的容量

    public int getCapacity() {

        return data.length;

    }



    // 判断数组是否为空

    public boolean isEmpty() {

        return size == 0;

    }



/*    // 在数组末尾添加元素

    public void addLast(E e) {

        if (size == data.length)

            throw new IllegalArgumentException("AddLast failed.Array is full.");

        data[size] = e;

        size++;

    }*/



    // 在数组末尾添加元素(复用add方法)

    public void addLast(E e) {

        add(size, e);

    }



    // 在数组头部添加元素(复用add方法)

    public void addFirst(E e) {

        add(0, e);

    }



    // 数组指定位置添加元素

    public void add(int index, E e) {

//        if (size == data.length)

//            throw new IllegalArgumentException("Add failed.Array is full.");

        if (index < 0 || index > size)

            throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size");

        if (size == data.length)

            resize(2 * data.length);

        for (int i = size - 1; i >= index; i--)

            data[i + 1] = data[i];

        data[index] = e;

        size++;

    }



    // 获取index索引位置的元素

    public E get(int index) {

        if (index < 0 && index >= size) {

            throw new IllegalArgumentException("Get failed.Index is illegal.");

        }

        return data[index];

    }



    // 获取第一个元素

    public E getFirst() {

        return this.get(0);

    }



    // 获取最后一个元素

    public E getLast() {

        return this.get(size - 1);

    }



    // 修改index索引位置的元素

    public void set(int index, E e) {

        if (index < 0 || index >= size) {

            throw new IllegalArgumentException("Set failed.Index is illegal.");

        }

        data[index] = e;

    }



    // 查找数组中是否存在元素e

    public boolean contains(E e) {

        for (int i = 0; i < size; i++) {

            if (data[i] == e) {

                return true;

            }

        }

        return false;

    }



    // 查找数组中元素e所在的索引,如果不存在元素e,则返回-1

    public int find(E e) {

        for (int i = 0; i < size; i++) {

            if (data[i] == e) {

                return i;

            }

        }

        return -1;

    }



    // 从数组中删除index位置的元素,返回删除的元素

    public E remove(int index) {

        if (index < 0 || index >= size) {

            throw new IllegalArgumentException("Remove failed.Index is illegal");

        }

        E ret = data[index];

        for (int i = index + 1; i < size; i++) {

            data[i - 1] = data[i];

        }

        size--;

        // loitering objects != memory leak 手动释放内存空间

        data[size] = null;

//        if(size == data.length / 2) {

//            resize(data.length / 2);

//        }

        // resize缩容优化方案(Lazy)

        if (size == data.length / 4 && data.length / 2 != 0) {

            resize(data.length / 2);

        }

        return ret;

    }



    // 删除数组第一个元素,返回删除的元素

    public E removeFirst() {

        return remove(0);

    }



    // 删除数组最后一个元素

    public E removeLast() {

        return remove(size - 1);

    }



    // 删除数组中指定元素e

    public void removeElement(E e) {

        int index = find(e);

        if (index != -1) {

            remove(index);

        }

    }



    // 数组扩容

    private void resize(int newCapacity) {

        E[] newData = (E[]) new Object[newCapacity];

        for (int i = 0; i < size; i++) {

            newData[i] = data[i];

        }

        data = newData;

    }



    // 重写父类toString()方法

    @Override

    public String toString() {

        StringBuilder sb = new StringBuilder();

        sb.append(String.format("Array: size = %d , capacity = %d\n", size, data.length));

        sb.append('[');

        for (int i = 0; i < size; i++) {

            sb.append(data[i]);

            if (i != size - 1) {

                sb.append(',');

            }

        }

        sb.append(']');

        return sb.toString();

    }

}

基于动态数组Array实现的ArrayQueue:

public class ArrayQueue<E> implements Queue {



    private Array<E> array;



    public ArrayQueue() {

        array = new Array<>();

    }



    public ArrayQueue(int capacity) {

        array = new Array<>(capacity);

    }



    @Override

    public void enqueue(Object o) {

        array.addLast((E) o);

    }



    @Override

    public E dequeue() {

        return array.removeFirst();

    }



    @Override

    public Object getFront() {

        return array.getFirst();

    }



    @Override

    public int getSize() {

        return array.getSize();

    }



    @Override

    public boolean isEmpty() {

        return array.isEmpty();

    }



    @Override

    public String toString() {

        StringBuilder sb = new StringBuilder();

        sb.append("Queue:");

        sb.append("front [");

        for (int i = 0; i < array.getSize(); i++) {

            sb.append(array.get(i));



            if (i != array.getSize() - 1) {

                sb.append(", ");

            } else {

                sb.append("] tail");

            }

        }

        return sb.toString();

    }

}

测试队列ArrayQueue:

public class Main {



    public static void main(String[] args) {

        ArrayQueue<Integer> arrayQueue = new ArrayQueue<>(10);

        System.out.println("入队操作开始:");

        for (int i = 0; i < 10; i++) {

            arrayQueue.enqueue(i);

            // 入队操作

            System.out.println(arrayQueue);

        }

        // 打印入队10个元素之后的队列

        System.out.println(arrayQueue);



        // 出队操作

        arrayQueue.dequeue();

        System.out.println("出队操作开始:");

        System.out.println(arrayQueue);



    }

}

测试结果如下:

入队操作开始:

Queue:front [0] tail

Queue:front [0, 1] tail

Queue:front [0, 1, 2] tail

Queue:front [0, 1, 2, 3] tail

Queue:front [0, 1, 2, 3, 4] tail

Queue:front [0, 1, 2, 3, 4, 5] tail

Queue:front [0, 1, 2, 3, 4, 5, 6] tail

Queue:front [0, 1, 2, 3, 4, 5, 6, 7] tail

Queue:front [0, 1, 2, 3, 4, 5, 6, 7, 8] tail

Queue:front [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] tail

Queue:front [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] tail

出队操作开始:

Queue:front [1, 2, 3, 4, 5, 6, 7, 8, 9] tail

 

Process finished with exit code 0

 

4、数组队列的复杂度分析

E dequeue() 时间复杂度为O(n),因为出队底层操作是动态数组,出队操作实际上就是删除数组第一个元素,然后数组后面的元素全部往前移动一个位置,所以dequeue()时间复杂度为O(n)。

 

如果感兴趣的童鞋,可以观看我下一篇博客:敬请期待

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个经典的生产者消费者问题,可以使用 Python 的 `greenlet` 库来实现。以下是代码实现: ```python from greenlet import greenlet def producer(consumer): chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] for char in chars: while not consumer.switch(char): pass def consumer(): while True: char = producer_coroutine.switch() print(char) producer_coroutine = greenlet(producer) consumer_coroutine = greenlet(consumer) producer_coroutine.switch(consumer_coroutine) ``` 在这个例子中,我们同样定义了两个函数 `producer` 和 `consumer`,分别用来生产和消费数据。`producer` 函数往队列中不断添加字符,并通过 `switch` 方法切换到 `consumer` 函数执行。如果 `consumer` 函数返回了 False,则说明队列已经满了,需要等待 `consumer` 函数消费掉一些字符后才能继续添加字符。`consumer` 函数从队列中获取字符并打印到屏幕上,然后通过 `switch` 方法切换回 `producer` 函数执行。注意,我们使用了一个无限循环来不断获取队列中的字符,直到队列被清空。 接着,在主程序中,我们同样创建了两个 `greenlet` 对象作为协程,一个是生产者协程 `producer_coroutine`,另一个是消费者协程 `consumer_coroutine`。然后,我们通过调用 `producer_coroutine.switch(consumer_coroutine)` 方法,将协程切换到 `consumer` 函数执行。这样,我们就完成了生产者消费者的协程实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值