简体   繁体   English

Dequeue 方法未正确删除队列中的元素

[英]Dequeue method not correctly deleting elements within queue

My dequeue method currently does not delete the item I wish for it too, instead it deletes the last element from the collection.我的 dequeue 方法目前也不会删除我想要的项目,而是从集合中删除最后一个元素。 For example,例如,

If I add in the elements: 1, 2, 3 My toString method will return 1, 2, 3 as expected.如果我添加元素: 1, 2, 3 我的 toString 方法将按预期返回 1, 2, 3 。

Then when I use my driver to call dequeue, it should dequeue the 0th element, 1 in this case.然后当我使用我的驱动程序调用 dequeue 时,它​​应该使第 0 个元素出列,在这种情况下为 1。

Although, the method says "Removed element 1 from the queue" prompting that the T result variable has embodied the correct value, although the method does not work as expected, as when calling the toString method after to print the contents, it will print: 1, 2虽然,该方法说“Removed element 1 from the queue”提示T result变量已经体现了正确的值,虽然该方法没有按预期工作,因为在打印内容后调用toString方法时,它会打印: 1、2

Then when I call the enqueue method again, on the same queue, if I enqueue the String 3, it will print this as the new queue: 3, 2, 3然后,当我再次调用 enqueue 方法时,在同一个队列上,如果我将 String 3 加入队列,它将将此打印为新队列:3, 2, 3

I am confused as to where my logic error is, as I assume it is with the extreme case of the collection being filled, but I still run into errors with my dequeue method when the collection is not at max.我对我的逻辑错误在哪里感到困惑,因为我认为这是集合被填充的极端情况,但是当集合不是最大时,我的出队方法仍然遇到错误。 I attached my code below.我在下面附上了我的代码。

public class QueueRA<T> implements QueueInterface<T> {

    protected T[] items;
    protected int front, back, numItems; 
    
    @SuppressWarnings("unchecked")
    public QueueRA() {
        front = 0;
        numItems = 0;
        back = 0;
        items = (T[]) new Object[3];    
    }
    
    @Override
    public boolean isEmpty() {
        return numItems == 0;
    }

    @Override
    public void enqueue(T newItem) throws QueueException {
        if(numItems == items.length) {
            resize();
            enqueue(newItem);
        }
        else {
            items[back] = newItem;
            back = (back + 1) % items.length;
            numItems++;
        }
    }

    @Override
    public T dequeue() throws QueueException {
        T result;
        if(numItems != 0) {
            result = items[front];
            items[front] = null;
            front = (front + 1) % items.length;
            numItems--;
        }
        else {
            throw new QueueException("The queue does not contain any elements.");
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void dequeueAll() {
        back = 0;
        front = 0;
        numItems = 0;
        items = (T[]) new Object[3];
    }

    @Override
    public T peek() throws QueueException {
        T result;
        if(numItems != 0) {
            result = items[front];
        }
        else {
            throw new QueueException("The queue does not contain any elements.");
        }
        
        return result;
    }
    
    /**
     * 
     */
    @SuppressWarnings("unchecked")
    protected void resize() {
        T[] newItems = (T[]) new Object[numItems+4];
        
        for(int i = 0; i < numItems; i++) {
            newItems[i] = items[i];
        }
        
        this.front = 0;
        this.back = numItems;
        this.items = newItems;
    }

    /**
     * 
     */
    public String toString() {
        String toReturn = "";
        for(int i = 0; i < numItems; i++) {
            if( (i+1) == numItems) {
                toReturn = toReturn.concat(items[i] + " ");
            }
            else {
                toReturn = toReturn.concat(items[i] + ", ");
            }
        }
        return toReturn;
    }
    
}

Your toString() and resize() methods are wrong.您的 toString() 和 resize() 方法是错误的。

In your example code, you created an arraySize of 3 initially and then added 1, 2, and 3. This occupies all the 3 slots in the array and your numItems is set to 3. The front is set to 0 and back is also set to 0 because after adding 3, your algorithm is:在您的示例代码中,您最初创建了一个 3 的 arraySize,然后添加了 1、2 和 3。这占用了数组中的所有 3 个插槽,并且您的 numItems 设置为 3。前面设置为 0,后面也设置到 0 因为在添加 3 之后,你的算法是:

back = (back+1)%items.length;

back was initially 2. Now it is calculated as: back 最初是 2。现在计算如下:

-> (2+1)%3
-> 3%3
-> 0

So your back is 0 at this moment.所以此时你的背部为 0。

Now, when you call dequeue(), the front pops 1 out.现在,当您调用 dequeue() 时,前端会弹出 1。 So now your array looks like this:所以现在你的数组看起来像这样:
items[0] -> empty项目[0] -> 空
items[1] -> 2项目[1] -> 2
items[2] -> 3项目[2] -> 3
back = 0返回 = 0
front = 1前 = 1

So, when you enque next and add 3, your enqueue() method checks that number of items in the system is less than size of the array (2 < 3) and adds 3 to the location pointed by back (which is 0 now) and increments it to 1. So, your array looks like this now:因此,当您 enque next 并添加 3 时,您的 enqueue() 方法会检查系统中的项目数是否小于数组的大小 (2 < 3) 并将 3 添加到 back 指向的位置(现在为 0)并将其增加到 1。所以,你的数组现在看起来像这样:
items[0] -> 3项目[0] -> 3
items[1] -> 2项目[1] -> 2
items[2] -> 3项目[2] -> 3
back = 1返回 = 1
front = 1前 = 1

Now, in your toString() method, without considering the values of front and back, you start from 0 to end:现在,在您的 toString() 方法中,不考虑前后的值,您从 0 开始到结束:

for(int i = 0; i < numItems; i++) {
.
.
.
}

What you need to be doing is start at i = front.你需要做的是从 i = front 开始。 if front < back, that means that you travel lineraly from "front" to "back" and print everything.如果前 < 后,这意味着您从“前”到“后”线性旅行并打印所有内容。 If front > back then you do two loops:如果前 > 后然后你做两个循环:

for(int i=front; i < arr.length; i++) {
// Code to print arr[i]
}

for(int i=0; i < back; i++) {
// Code to print arr[i]
}

This way, it will print from front to end and then from 0 to back.这样,它将从前端打印到后端,然后从 0 打印到后端。

Also, your resize method is wrong for the same reason.此外,出于同样的原因,您的调整大小方法是错误的。 You cannot copy from 0 to numItems, you need to start the copy at "front" and then progress like how I wrote for the toString().您不能从 0 复制到 numItems,您需要从“前面”开始复制,然后像我为 toString() 编写的那样进行。 Doing this will ensure that your queue's order is preserved across multiple resizes.这样做将确保您的队列的顺序在多次调整大小时保持不变。

Adding to @Arun Subramanian's answer .添加到@Arun Subramanian 的回答中

Your resize() method was simply copying all of the elements sequentially from items to newItems , then setting front = 0 and back = numItems .您的resize()方法只是将所有元素从items顺序复制到newItems ,然后设置front = 0back = numItems Which would have been fine if you had implemented the queue sequentially.如果您按顺序实现队列,那会很好。 However, your implementation of a queue is not sequential, it's a circular / ring implementation.但是,您对队列的实现不是顺序的,它是一个循环/环形实现。 Therefor you have to copy the elements in a circular way.因此,您必须以循环方式复制元素。

One way to do this is mentioned in @ArunSubramanian's answer, "If front < back , that means that you travel linearly from front to back and print everything. If front > back then you do two loops." @ArunSubramanian 的回答中提到了一种方法, “如果front < back ,这意味着您frontback线性移动并打印所有内容。如果front > back则您执行两个循环。” Another way is to use a do-while loop with modular arithmetic, as in the following:另一种方法是使用带有模运算的 do-while 循环,如下所示:

@SuppressWarnings("unchecked")
protected void resize() {
    T[] newItems = (T[]) new Object[numItems + 4];
    
    int i = 0; // index used to copy items to newItems
    // do-while used in case the queue is full (i.e. front == back)
    do {
        newItems[i] = items[front];

        // modular arithmetic used to circle back on items
        front = (front + 1) % items.length;
        i += 1;
    } while(front != back);
    
    this.front = 0;
    this.back = numItems;
    this.items = newItems;
}

Similarly your toString() method can be implemented in the following way:同样,您的toString()方法可以通过以下方式实现:

@Override
public String toString() {
    String toReturn = "";
    
    // need this check, otherwise do-while will illegally access items[0]
    if(!isEmpty()) {
        int len = items.length;
        int i = front;
        
        // do-while used in case front == back
        do {
            String delim = ((i+1) % len == back) ? " " : ", ";

            toReturn += items[i] + delim;
            
            i = (i+1) % len; // modular arithmetic used to circle back
        } while(i != back);
    }
    return toReturn;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM