2017-04-23 3 views
0

円配列を使用してキューADTを実装しました。しかし、私は円形の配列のすべての内容を一杯になったら大きな配列にコピーできるようにしたい。私はJavaでsystem.arraycopyについて読んだことがあるが、この関数はC++では存在しない。以下のエンキュー関数では、配列がいっぱいでエラーをスローするのではなく、より大きな配列にコピーする必要があります。配列サイズがいっぱいのときに円形配列の内容を大きな配列にコピーする方法

マイコード:

template <class Obj> 

class Circular_Queue 
{ 
    int MAX; 
    private: 
    Obj *cqueue_arr; 
    Obj *cqueue_arr2; 
    int front, rear; 
    public: 
    Circular_Queue() 
    { 
     cqueue_arr = NULL; 
     cout << "Enter size of the queue:"; 
     cin >> MAX; 
     cqueue_arr = new Obj[MAX]; 
     rear = -1, front = -1; 
    } 

    ~Circular_Queue() { 
     delete[]cqueue_arr; 
    } 

    void qfront() { 
     if (front == -1) 
     { 
      throw QueueEmptyException(); 
     } 
     cout << "Front item is : " << cqueue_arr[front] << endl; 
    } 

    //Insert into Circular Queue 
    void enqueue(Obj item) 
    { 
     int i; 

     if ((front == 0 && rear == MAX - 1) || (front == (rear + 1)% MAX)) 
     { 
      Obj* cqueue_arr2 = new Obj[MAX * 2];  // Creates a bigger array. 
      for (int i = 0; i < (MAX * 2); i++) { // This section doesnt workas intended. 
       cqueue_arr2[i] = cqueue_arr[i]; 
      } 

     } 
     if (front == -1) 
     { 
      front = 0; 
      rear = 0; 
     } 
     else 
     { 
      if (rear == MAX - 1) 
       rear = 0; 
      else 
       rear = ((rear + 1) % MAX); 
     } 
     cqueue_arr[rear] = item; 
     cout << "Insertion Success!!!\n"; 
     cout << "The number of space left in the queue is "; 
     cout << MAX - (rear + 1) << endl; 
     cout << "          \n"; 
     cout << "Content of new array is:"; 
     for (int i = 0; i < MAX * 2; i++) 
      cout << cqueue_arr[i] << " "; 
    } 

    // Delete from Circular Queue 
    Obj dequeue() 
    { 
     if (front == -1) 
     { 
      throw QueueEmptyException(); 
     } 
     cout << "Element deleted from queue is : " << cqueue_arr[front] << endl; 
     if (front == rear) 
     { 
      front = -1; 
      rear = -1; 
     } 
     else 
     { 
      if (front == MAX - 1) 
       front = 0; 
      else 
       front = ((front + 1) % MAX); 
     } 
    } 

    //Display Circular Queue 

    void display() 
    { 
     int front_pos = front, rear_pos = rear; 
     if (front == -1) 
     { 
      cout << "Cannot display, Queue is EMPTY!\n"; 
      return; 
     } 
     cout << "Circular Queue elements are:\n"; 
     if (front_pos <= rear_pos) 
     { 
      while (front_pos <= rear_pos) 
      { 
       cout << cqueue_arr[front_pos] << " "; 
       front_pos++; 
      } 
     } 
     else 
     { 
      while (front_pos <= MAX - 1) 
      { 
       cout << cqueue_arr[front_pos] << " "; 
       front_pos++; 
      } 
      front_pos = 0; 
      while (front_pos <= rear_pos) 
      { 
       cout << cqueue_arr[front_pos] << " "; 
       front_pos++; 
      } 
     } 
     cout << endl; 
    } 
}; 
+0

2つのアレイのサイズが異なります。未定義の動作を避けるために、コピーされる要素の数は、より大きな配列の要素の数ではなく、SMALLER配列内の要素の数である必要があります。もちろん、両方の配列のライフタイムを管理するという問題があります。これはコードでも何もしません。 – Peter

+0

ありがとうございます。私はそれを考慮に入れました。 – Awani

答えて

1

主な問題は、範囲外の配列にアクセスしているということです。新しいサイズではなく、既存のサイズをループする必要があります。また、あなただけの新しい配列を破棄している、あなたは、この議論の余地のすべてになるだろうだけではなく、Data[]でのstd ::ベクトルを使用して、脇として、すなわち

if ((front == 0 && rear == MAX - 1) || (front == (rear + 1)% MAX)) 
{ 
    auto newMax = MAX * 2; 
    Obj* cqueue_arr2 = new Obj[newMax];  // Creates a bigger array. 
    for (int i = 0; i < (MAX); i++) { // loop over original array size, not new size 
     cqueue_arr2[i] = cqueue_arr[i]; 
    } 
    // remember to actually use the new array, and discard the old one. 
    delete[] cqueue_arr; 
    cqueue_arr = cqueue_arr2 
    MAX = newMax; 
} 

、古いものと新しい配列でスワップを削除する必要があります。できるだけコピーを避けるように効率的に成長します(realloc()と似ています)。また、他のいくつかの制限(現在の実装ではデフォルトのコンストラクタとコピー代入演算子が必要です)を避け、すべてのアクセスがポインタ演算にインライン展開されるので、生ポインタを使用して何も得られません。成長の部分を除いて、実装はほぼ同じままで、ちょうどqueue_vec.push_back(val);になります。

また、コンストラクタでcinを使用することは悪いことです。代わりにパラメータとしてintを渡すだけです。あなたは、cinからmain()にそれを読むことができます。そうすれば、あなたのクラスはIOを妨げることなく他の場所で使うことができます。

+0

ありがとうございます。これは役に立ちました。私は古い配列の代わりに新しい配列をループしていることに気付かなかった。コンストラクターに関しては、私はアドバイスされたパラメーターとして値MAXを渡しました。 Circular_Queue(int MAX)..しかし、メインプログラムで "Circular_Queue cqi;"を実行したときにエラーが発生しました。エラーメッセージ:Circular_Queueクラスのデフォルトコンストラクタが存在しません Awani

+0

'明示的Circular_Queue(int max = 128);'をコンストラクタとして追加すると、デフォルトのコンストラクタがあります(指定されていない場合はmaxを128に設定します)。メインでmaxを指定する場合は、 'Circular_Queue cqi(1024);'のように構成するか、intを渡す必要があります。また、私は本当に[C++の本を読む]ことをお勧めします(http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)。 –

+0

ありがとうございます – Awani

0

私はそれがあなたにそれを解決するヒントを与えることを望むと思います。

まず、stlやboostの既存のデータ型が最適化され、安定していることを推奨します。

第2に、配列をコピーするだけです...私はそうするでしょう。 (TargetArrayが事前に割り当てられるべきである。あなたがしたい場合は、あなただけの機能でそれを割り当てることができます。)

typedef Obj value_type; 
    int Clone(Obj *&TargetArray) { 
      unsigned int curArraySize=sizeof(value_type)*`YourArraySize' 
      memcpy(TargetArray,cqueue_arr, curArraySize); 
      TargetArray[curArraySize+1]=NULL; 
      return curArraySize; 
    } 

グッドラック

0

はあなたのジョセフ・アイルランドとグァンウン-チュンカンありがとうございます。あなたの助言とさらなる研究を続けて、私のコードは意図したとおりに動作します。これは私がやったことです。示す2つの整数変数として '

void resize() { 

    auto newMAX = 2 * MAX; 

    Obj *cqueue_arr2 = new Obj[newMAX]; 
    int i = 0;         // controls new array 

                  position 
    int j = front;       // controls old array 
                  position 
    bool rearReached = false; 
    while (!rearReached) { 
     rearReached = j % MAX == rear;  // is true when rear is 
                   reached 
     cqueue_arr2[i] = cqueue_arr[j % MAX]; 
     i++; 
     j++; 
    } 
    front = 0; 
    rear = MAX - 1; 
    cqueue_arr = cqueue_arr2; 
    MAX = newMAX;` 

新旧アレイ内の項目の位置を制御します。これは、フロント位置が常にインデックス0ではない循環キューに対しては完全に機能します。すべてのアイテムをコピーした後、新しいアレイでインデックスをfront = 0およびrear = MAX -1に設定します。これが他人を助けることを望みます。

+0

また、2回のmemcpy呼び出しで行うこともできます。 – Donnie

関連する問題