利用可变长度循环数组实现队列

队列可以基于数组或者链表实现。如果选择基于数组实现,效率会更高,但是数组长度固定,需要在队列长度超限或者队列长度过短时对数组长度进行调整。

如果直接采用数组存储队列,当队列头部出列一个元素后要依次迁移大量后继元素增加无谓开销。改进的方式是采用循环数组,循环数组用两个“指针”标示队列头尾部,当队列头部元素出列,则向后移动头指针,当队列尾部入列元素,则向后移动尾指针。

注意,一旦尾指针被移动到数组最末尾,则应当将尾指针归0,再入列新元素(当然此时头指针肯定是指向了数组的中间某个位置,头尾指针不会交叉,因为当队列长度达到数组长度时已经将数组扩容了)。
尾指针归0
代码如下:

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * 利用循环数组实现的队列数据结构,能够通过修改队列head来减少dequeue时的数据迁移量
 * @param <Item> 队列元素数据类型
 */
public class ModifiedResizingArrayQueue<Item> implements Iterable<Item> {
    private Item[] queue;  //用于存储队列的数组
    private int size;      //队列的长度
    private int head;      //队列的头部
    private int tail;      //队列的尾部

    public ModifiedResizingArrayQueue() {
        this.queue = (Item[]) new Object[2];
        this.size = 0;
        this.head = 0;
        this.tail = 0;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public int getSize() {
        return size;
    }

    private void resize(int newSize) {
        assert newSize >= size;
        Item[] newQueue = (Item[]) new Object[newSize];
        for (int i = 0; i < size; ++i) {
            newQueue[i] = queue[(head + i) % queue.length];
        }
        queue = newQueue;
        head = 0;
        tail = size;
    }

    public void enqueue(Item item) {
        //当队列占满数组时,将数组扩容一倍
        if (size == queue.length) {
            resize(2 * queue.length);
        }
        queue[tail] = item;
        tail++;
        //如果队列尾部已经到达数组尾部,则先将队列尾部指向数组最前才能添加元素
        if (tail == queue.length) {
            tail = 0;
        }
        size++;
    }

    public Item dequeue() {
        //当队列短于数组1/4时,将数组缩减一半
        if (size == queue.length / 4) {
            resize(queue.length / 2);
        }
        if (size == 0) {
            throw new RuntimeException("Queue empty!");
        }
        Item item = queue[head];
        queue[head] = null;
        head++;
        size--;
        return item;
    }

    @Override
    public Iterator<Item> iterator() {
        return new QueueIterator();
    }

    private class QueueIterator implements Iterator<Item> {
        private int index = 0;


        @Override
        public boolean hasNext() {
            return index < size;
        }

        @Override
        public Item next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            Item item = queue[(head + index) % queue.length];
            index++;
            return item;
        }
    }

    public static void main(String[] args) {
        ModifiedResizingArrayQueue<String> strQueue = new ModifiedResizingArrayQueue<>();
        System.out.println("Empty? " + strQueue.isEmpty());
        System.out.println("Current size: " + strQueue.getSize());
        strQueue.enqueue("to");
        strQueue.enqueue("be");
        strQueue.enqueue("or");
        System.out.println("Current size: " + strQueue.getSize());
        System.out.println(strQueue.dequeue());
        System.out.println(strQueue.dequeue());
        System.out.println(strQueue.dequeue());
        System.out.println("Current size: " + strQueue.getSize());
        System.out.println("当队列为空继续出列则报错:");
        strQueue.dequeue();
        System.out.println("Current size: " + strQueue.getSize());
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
长度为10的数组实现队列最优思路是使用循环队列循环队列可以解决普通队列在出队后导致的空间浪费问题。循环队列需要维护两个指针:队头指针 front 和队尾指针 rear,其中 front 指向队头元素,rear 指向队尾元素的下一个位置。 当队列为空时,front 和 rear 指向同一个位置,当队列满时,rear 的下一个位置就是 front,即 (rear+1) % n == front,其中 n 表示数组长度。因此,当 rear+1 % n == front 时,队列就已经满了,再插入元素就会导致队列溢出。 对于入队操作,将元素插入到 rear 指向的位置,并将 rear 向后移动一个位置。对于出队操作,将 front 指向的元素弹出,并将 front 向后移动一个位置。这样,队列长度就是 rear - front。 具体实现细节可以参考下面的代码: ```python class Queue: def __init__(self): self.array = [None] * 10 self.front = 0 self.rear = 0 def is_empty(self): return self.front == self.rear def is_full(self): return (self.rear + 1) % len(self.array) == self.front def enqueue(self, element): if self.is_full(): raise Exception('Queue is full') self.array[self.rear] = element self.rear = (self.rear + 1) % len(self.array) def dequeue(self): if self.is_empty(): raise Exception('Queue is empty') element = self.array[self.front] self.front = (self.front + 1) % len(self.array) return element ``` 在这个实现中,我们使用取模运算来实现循环队列。当 rear 超出数组的范围时,将 rear 的值重新赋为 0,表示下一个元素将插入到数组的第一个位置。同理,当 front 超出数组的范围时,将 front 的值重新赋为 0,表示下一个元素将弹出数组的第一个位置。这样就解决了普通队列在出队后导致的空间浪费问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值