数据结构与算法基础--queue(java)

其实在上一堂课讲到了queue的接口设计。本来想将queue整个包含在上一篇文章中,但是对于队列的问题包含了很多东西,便想单独列出来说明一下。

首先我们先了解什么是队列:

队列同样是一种特殊的线性表,其插入和删除的操作分别在表的两端进行,队列的特点就是先进先出(First In First Out)。我们把向队列中插入元素的过程称为入队(Enqueue),删除元素的过程称为出队(Dequeue)并把允许入队的一端称为队尾,允许出的的一端称为队头,没有任何元素的队列则称为空队。

上篇文章中,由我的教授提出的接口是:

public interface Queue<Item> {
    /**
     * Update this Queue by adding an item on the newest end;
     * @param item the item to add;
     */
    void enqueue(Item item);
    /**
     * Update this Queue by taking the oldest item off the queue
     * @return the item or null if there is no such item;
     */
    Item dequeue();
    /**
     * @return true if the queue is empty;
     */
    boolean isEmpty();
}

这个接口都没有表明这是一个顺序队列还是一个循环队列。当然对于实际应用,顺序队列会消耗掉大量的内存空间。其中enqueu的时间复杂度是O(1),但是如果在dequeue()的时候进行位移操作,那么整个程序的复杂度为O(n).而对于循环列表,enqueue仍然是O(1)的复杂度,dequeue则降低为O(1)。

其中关于循环队列在建立的时候包含一个问题,如果将整个队列全部装满,那么front==rear的判断条件符合队列空,也符合队列满!

所以在建立队列的时候,有两种方法来解决这个问题:

1)另设一个标识为来判断是否队列满了;

2)少一个元素空间,规定front指针在rear指针的下一个位置上,即:

  队空时:front=rear;

  队满时:front=(rear+1)%maxsize

下面,我自己对queue接口进行实现。当然,这是一个循环队列的实现。

其中使用第二种方法对队满进行判断:

public class MyQueue<Item> implements Queue<Item>{
    
    private static int DEFAULT_SIZE=10;
    private Item elements[];
    private int front,rear;
    private int size;
    public MyQueue(){
        elements=(Item[])new Object[DEFAULT_SIZE];
        front=rear=0;
        size=0;
    }
    
    public MyQueue(int capacity)
    {
        elements=(Item[])new Object[capacity];
        front=rear=0;
        size=0;
    }
    
    public int size(){
        return size;
    }
    
    public boolean isEmpty(){
        return front==rear;
    }
    
    public void enqueue(Item data){
        if(this.front==(this.rear+1)%this.elements.length){
            ensureCapacity(this.elements.length*2+1);
        }
        elements[rear]=data;
        this.rear=(this.rear+1)%this.elements.length;
        size++;
    }
    
    public Item dequeue(){
        Item temp=this.elements[front];
        this.front=(this.front)%this.elements.length;
        size--;
        return temp;
    }
    
    public void ensureCapacity(int capacity){
        Item[] old=this.elements;
        this.elements=(Item[])new Object[capacity];
        int j=0;
        for(int i=this.front;i!=this.rear;i=(i+1)%old.length){
            elements[j++]=old[i];
        }
        front=0;
        rear=j;
    }
    
}

 

其中扩展了ensureCapaciy()方法。主要是对array长度不够,而扩展队列的扩展。

 

其实可以看到,循环队列不会要求enqueue的时候将元素往前移动,而降低了复杂度。

但是,今天上课教授告诉我,用LinkList去实现队列和堆栈是一种更好的方法

我:??????

那我们下一次将会使用LinkList实现队列和堆栈。

转载于:https://www.cnblogs.com/DSNFZ/articles/7554992.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值