【问题标题】:Increasing capacity of circular queue in C++在 C++ 中增加循环队列的容量
【发布时间】:2014-11-16 02:38:20
【问题描述】:

我正在学习队列,并正在尝试编写一种方法来使用动态数组更改循环队列的最大容量。这就是我的代码现在的样子。

void ArrayQueue::setCapacity(unsigned newCapacity){
if(newCapacity == 0 || newCapacity < this->getSize()){
    throw QueueException("setCapacity()", "invalid new capacity");
} else if(newCapacity != this->getSize()){
    Item * tempArray = new Item[newCapacity];
    for(unsigned i=0; i<newCapacity; i++){
        tempArray[i] = myArray[i];
    }
    Item * oldArray = myArray;
    myArray = tempArray;
    delete [] oldArray;
}
this->myCapacity = newCapacity;
}

但是,当我减少容量时,我无法获得 myFirst 和 myLast 值的断言。我知道我需要编写代码来解决条目已环绕但对如何执行此操作感到困惑的情况。

我要通过的测试代码如下:

    ArrayQueue q5(10);
for (int i = 0; i < 10; i++){
    q5.append(i+1);
}
for (int i = 0; i < 7; i++){
    q5.remove();
}
assert( q5.getCapacity() == 10 );
assert( q5.getSize() == 3 );
assert( !q5.isEmpty() );
assert( !q5.isFull() );
assert( q5.getFirst() == 8 );
assert( q5.getLast() == 10 );

//reduce the capacity
q5.setCapacity(5);
assert( q5.getCapacity() == 5 );
assert( q5.getSize() == 3 );
assert( !q5.isEmpty() );
assert( !q5.isFull() );
assert( q5.getFirst() == 8 );
assert( q5.getLast() == 10 );

我正在传递我的第一组断言,但第二个 getFirst 断言失败。

你能给我一个正确的方向吗?谢谢。

【问题讨论】:

  • 您的 for 循环不正确,如果您增加队列,myArray[i] 将会越界。
  • 如果您的 ArrayQueue 有一个需要容量的构造函数,那么您可以编写比您发布的更简单的函数。

标签: c++ arrays dynamic queue capacity


【解决方案1】:

我可以建议使用以下内容重写此内容:

#include <algorithm>
//...
void ArrayQueue::setCapacity(unsigned newCapacity)
{
    if(newCapacity == 0 || newCapacity < this->getSize()){
        throw QueueException("setCapacity()", "invalid new capacity");
    ArrayQueue tempQ(newCapacity);
    for(unsigned i=0; i< capacity; i++)
        tempQ.append(myArray[i]);
    std::swap(myArray, tempQ.myArray);
    std::swap(capacity, tempQ.capacity);
    std::swap(size, tempQ.size);
}

这是如何工作的?好吧,我们创建一个具有必要容量的临时ArrayQueue。然后我们所做的就是将数据复制到临时对象。之后,我们用this 交换临时对象。

完成。

临时对象因旧数据而死,而this 被设置为新数据。这是copy/swap 成语的变体。这需要ArrayQueue 的有效析构函数——一旦你有了它,它就变成了小菜一碟。

注意,如果有更多的成员变量,它们也需要交换。我只是交换了你发布的那些。我猜你有一个size 成员变量,所以如果你命名它不同,然后用你使用的名称替换它。底线 - 用tempQ 交换所有内容,你应该没问题。

如果您不知道 std::swap 做什么,它会按照它所说的去做。它只是将这两个项目相互交换——没什么特别的,只是使用一个函数来做这件事很方便。

【讨论】:

    【解决方案2】:
    for(unsigned i=0; i<newCapacity; i++){
        tempArray[i] = myArray[i];
    }
    

    如果您的新容量更大,那么您将使用无效索引访问 myArray

    【讨论】:

      【解决方案3】:

      尽我所能弄清楚您的问题,您引用的是在其他地方抛出的断言,而不是您发布的代码片段。由于您没有发布您认为有问题的代码,因此不太可能有人会给您答案。

      但是,我确实在您发布的代码片段中看到了一个可能的错误。您增加数组大小的代码:

      Item * tempArray = new Item[newCapacity];
      for(unsigned i=0; i<newCapacity; i++){
          tempArray[i] = myArray[i];
      }
      Item * oldArray = myArray;
      myArray = tempArray;
      delete [] oldArray;
      

      例如,假设 myArray 的旧大小为 20,而您将其增加到 40。

      您将分配一个新的 40 元素 tempArray。

      然后继续将前 40 个元素从 myArray 复制到 tempArray。

      未定义的行为。

      【讨论】:

      • 我刚刚用失败的测试代码更新了我的问题。在失败的断言中,我降低了容量。 myFirst 和 myLast 值在原始容量下是正确的,但是在将容量减半后,它们就不起作用了。 myFirst 是 0,而 myLast 是 5,这不应该是这种情况。
      • @TheFaceOfBoe 这是否将容量设置为 10? ArrayQueue q5(10); 如果是这样,我最初的评论仍然有效——你可以用比你写的更简单的方式对 setCapacity 进行编码。如此简单,即使不是不可能出现错误,也将非常困难。我会发布一个答案,但需要确认此构造函数设置了容量...
      • @PaulMcKenzie 是的,这确实将容量设置为 10。但是,我不确定您在想什么更简单的方法。我仍然需要分配一个新数组并将每个元素复制到新数组中,这就是我在这里要做的。
      • @TheFaceOfBoe 请参阅下面的答案。使用已经编码的内容对您有利,这就是我给出的答案正在做的事情......
      猜你喜欢
      • 2021-09-29
      • 2015-04-15
      • 2014-01-05
      • 1970-01-01
      • 1970-01-01
      • 2014-01-07
      • 2019-07-15
      • 1970-01-01
      • 2014-10-21
      相关资源
      最近更新 更多