0

キューについて学んでおり、動的配列を使用して循環キューの最大容量を変更するメソッドを作成しようとしています。これが私のコードが今どのように見えるかです。

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 );

最初の一連のアサーションはパスしていますが、2 番目の getFirst アサーションは失敗しています。

正しい方向へのポインタを教えていただけますか?ありがとう。

4

3 に答える 3

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 つのアイテムを互いに交換するだけです。特別なことはなく、関数を使用してこれを行うだけで便利です。

于 2014-11-16T03:34:40.373 に答える
0
for(unsigned i=0; i<newCapacity; i++){
    tempArray[i] = myArray[i];
}

新しい容量が大きい場合、無効なインデックスで myArray にアクセスします

于 2014-11-16T02:44:06.927 に答える
0

あなたの質問を理解できる限り、投稿したコードフラグメント以外の場所でスローされたアサーションを参照しています。あなたが問題のあるコードを投稿していないので、誰もあなたに答えてくれることはまずありません。

ただし、投稿されたコード フラグメントにバグの可能性があります。配列のサイズを増やすコード:

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 にコピーします。

未定義の動作。

于 2014-11-16T02:45:18.403 に答える