【问题标题】:Why is the array based queue not working as it should?为什么基于数组的队列不能正常工作?
【发布时间】:2018-12-28 05:11:43
【问题描述】:

我已经为基于数组的队列编写了代码。它的行为非常奇怪,就像我使用 for 循环将 0,1,2,3,4 排入队列,但插入队列的是 0,0,1,2,3。

dequeue 也在抛出ArrayOutOfBoundsException,我不知道为什么。

我使用的入队逻辑是将元素放在一个简单的数组中。额外的一件事是,如果大小接近容量的一半,我会增加数组的容量。

对于出队,如果大小小于容量的三分之一,我将减少容量。我还保留了一个弹出计数器,它从数组的开头弹出元素。

以下是我用过的代码:

class ArrayQueue {

      private int[] arr;
      private int size;
      private int capacity;
      private int popped = 0;

      public ArrayQueue(int capacity) {

        this.capacity = capacity;
        size = 0;
        arr = new int[capacity];
      }

      public int size() {
        return size;
      }

      public int capacity() {
        return capacity;
      }

      public void enqueue(int ele) {

        size++;

        if(size >= capacity/2) {

            capacity = capacity*2;

            int[] nArr = new int[capacity];

            for(int i=0;i<size;i++)
                nArr[i] = arr[i];

            arr = nArr;

        }

        arr[size] = ele;

      }

      public void dequeue() {

        size--;

        System.out.println(arr[popped]+" removed");

        if(size <= capacity/3) {

            capacity = capacity/2;

            int[] nArr = new int[capacity];

            for(int i=0;i<size;i++)
                nArr[i] = arr[i];

            arr = nArr;

        }

        int[] nArr = new int[capacity];

        for(int i=0;i<popped;i++)
            nArr[i] = arr[i];

        for(int i=popped+1;i<size;i++)
            nArr[i-1] = arr[i];

        arr = nArr;

        popped++;

    }

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

    public void showQueue() {

        for(int i=0;i<size;i++)
            System.out.println("| "+arr[i]+" |");

    }
    }



    public static void main(String[] args) {

        ArrayQueue a = new ArrayQueue(10);

        System.out.println("Starting size "+a.size());

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

            a.enqueue(i);
            System.out.println("Current size is "+a.size());
            System.out.println("Current capacity is "+a.capacity());

        }

        System.out.println();

        a.showQueue();

        System.out.println();

        a.dequeue();

        System.out.println("Size: "+a.size());
        System.out.println("Current capacity is "+a.capacity());

        a.dequeue();

        System.out.println("Size: "+a.size());
        System.out.println("Current capacity is "+a.capacity());

        a.dequeue();

        System.out.println("Size: "+a.size());
        System.out.println("Current capacity is "+a.capacity());

        a.dequeue();

        System.out.println("Size: "+a.size());
        System.out.println("Current capacity is "+a.capacity());


    }

我得到的输出是:

Starting size 0
Current size is 1
Current capacity is 10
Current size is 2
Current capacity is 10
Current size is 3
Current capacity is 10
Current size is 4
Current capacity is 10
Current size is 5
Current capacity is 20

| 0 |
| 0 |
| 1 |
| 2 |
| 3 |

0 removed
Size: 4
Current capacity is 10
1 removed
Size: 3
Current capacity is 5
0 removed
Size: 2
Current capacity is 5
0 removed
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
    at ArrayQueue.dequeue(Code.java:228)
    at Code.main(Code.java:76)

【问题讨论】:

  • 我最好的建议是:学会使用你的调试器。我的第二个最佳建议是:您的 arr = new int[capacity];capacity 零填充该数组(这里是十)。
  • 数组是零索引的,这意味着第一个元素位于arr[0]

标签: java arrays queue


【解决方案1】:

当你做deQueue()操作时,你应该总是remove an element at index 0。所以你no need increment poppedIt should be always 0 (index 0)

    public void dequeue() {

        size--;

        System.out.println(arr[popped] + " removed");

        if (size <= capacity / 3) {

            capacity = capacity / 2;

            int[] nArr = new int[capacity];

            for (int i = 0; i < size; i++)
                nArr[i] = arr[i];

            arr = nArr;

        }

        int[] nArr = new int[capacity];

/*      for (int i = 0; i < popped; i++)
            nArr[i] = arr[i]; //Not required as popped is always 0
*/
        for (int i = popped + 1; i < size; i++)
            nArr[i - 1] = arr[i];

        arr = nArr;

        //popped++; // not required as we remove first element

    } 

【讨论】:

  • 啊,是的,我完全错过了。谢谢你:)
【解决方案2】:

对于入队,您的代码应该是这样的。在您的代码中,当您之前增加大小时会出现问题。

public void enqueue(int ele) {



      if(size >= capacity/2) {

          capacity = capacity*2;

          int[] nArr = new int[capacity];

          for(int i=0;i<size;i++)
              nArr[i] = arr[i];

          arr = nArr;

      }

      arr[size] = ele;
      size++;

    }

对于出列,您不应该在每次需要删除 0 索引 时都执行基于 Popped 的操作。

    public void dequeue() {

    System.out.println(arr[0] + " removed");
    if (size <= capacity / 3) {
        capacity = capacity / 2;
        int[] nArr = new int[capacity];
        for (int i = 0; i < size; i++)
            nArr[i] = arr[i];
        arr = nArr;
    }

    int[] nArr = new int[capacity];

    for (int i = 1; i < size; i++) // every time we need to pop first index
        nArr[i - 1] = arr[i];

    arr = nArr;

    popped++;
    size--;

}

【讨论】:

  • 如果需要,可以在方法结束时调整数组大小
猜你喜欢
  • 2014-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-16
  • 2019-01-04
  • 2020-09-03
相关资源
最近更新 更多