2017-02-03 6 views
0

私は時には自分のニーズに合わせて拡大する必要があるダイナミックな正方形の2D配列で作業しています。拡大部分はこのように、配列の各境界に新しいケースを追加することで構成されています動的な2D配列の中央をより小さなもので埋めるにはどうすればよいですか?

enter image description here

これを実現するために、私は最初の一時的な他の2次元配列で私の実際の2D配列の内容をコピーします同じサイズ。次に、新しい2D配列を作成し、新しい配列の元の内容をコピーします。

新しいアレイの途中で古いアレイの内容を簡単にコピーする方法はありますか?私がこれまでに発見した唯一の方法は、唯一のセクションのための2つを使用することです:

for(int i = 1; i < arraySize-1; i++) 
{ 
    for(int j = 1; j < arraySize-1; j++) 
    { 
     array[i][j] = oldArray[i-1][j-1]; 
    } 
} 

しかし、これを達成するために何の迅速な方法が存在しない場合、私は思ったんだけど。私はstd :: fillの使用について考えましたが、この特定の場合にどのように使用できるかはわかりません。

マイEnlargeArray機能:

template< typename T > 
void MyClass<T>::EnlargeArray() 
{ 
    const int oldArraySize = tabSize; 

    // Create temporary array 
    T** oldArray = new T*[oldArraySize]; 
    for(int i = 0; i < oldArraySize; i++) 
    { 
     oldArray[i] = new T[oldArraySize]; 
    } 

    // Copy old array content in the temporary array 
    for(int i = 0; i < arraySize; i++) 
    { 
     for(int j = 0; j < arraySize; j++) 
     { 
      oldArray[i][j] = array[i][j]; 
     } 
    } 

    tabSize+=2; 

    const int newArraySize = arraySize; 

    // Enlarge the array 
    array= new T*[newArraySize]; 
    for(int i = 0; i < newArraySize; i++) 
    { 
     array[i] = new T[newArraySize] {0}; 
    } 

    // Copy of the old array in the center of the new array 
    for(int i = 1; i < arraySize-1; i++) 
    { 
     for(int j = 1; j < arraySize-1; j++) 
     { 
      array[i][j] = oldArray[i-1][j-1]; 
     } 
    } 

    for(int i = 0; i < oldArraySize; i++) 
    { 
     delete [] oldArray[i]; 
    } 
    delete [] oldArray; 
} 
+1

あなたはtmpアレイにコピーして、新しいアレイにコピーします。より大きな配列にコピーしてポインターを入れ替えることが簡単にできます。 –

+1

Btw、あなたは既存の配列を拡大する前に*メモリを解放しないでください。そうすればメモリリークが発生します。 –

+1

内部ループのデータはシーケンシャルなので、memcpy(array [i] [1]、oldArray [i-1] [0]、sizeof(T)*(arrysize - 2)) ' –

答えて

2

私の新しい配列の真ん中に古い配列の内容をコピーする任意の簡単な方法はありますか?

は(質問されないと仮定すると、 "私は2D for -loopよりも良い行うことができますか?"。)

短い答え:何を - あなたの配列が必要になりますR行とC列を持っている場合R*C操作を実行して、すべてを繰り返し実行する必要があります。

std::fillなどのアルゴリズムは、内部的にすべての要素を処理する必要があります。


代替答え:あなたの配列は、巨大であり、あなたは、配列の独立したサブセットを扱う複数のスレッドでコピー操作を分割、 偽共有を避けるために確認している場合でし(これは多くの要因とハードウェアに依存します - 研究/実験/プロファイリングが必要です)

1

まず、std::make_unique<T[]>を使用して配列の有効期間を管理できます。サイズがrow_count * col_countの単一の配列を割り当て、(col, row)のペアを配列インデックスに変換する簡単な算術演算を実行すると、配列を連続的にすることができます。ゼロで最初と最後の行を埋めるために使用std::fill

  • :次に、行優先順を想定。
  • std::copyを使用して、古い行を中間の行の中央にコピーします。
  • 単純な割り当てを使用して、中央の行の先頭と最後のセルを0で埋めます。
1

実行なしアレイを拡大します。それをそのまま保ち、新しいメモリをに割り当てます。境界線はのみです。次に、クラスの公開インタフェースでは、オフセットの計算をに適合させます。

クラスのクライアントには、配列が拡大されたように見えますが、実際には想定された拡大に実際には触れられていないようです。欠点は、配列内容の記憶域がもはや連続していないことです。ここで

は、私が使用する理由を見ることができないので、 std::vectorを使用して、おもちゃの一例である new[]delete[]

#include <vector> 
#include <iostream> 
#include <cassert> 

template <class T> 
class MyClass 
{ 
public: 
    MyClass(int width, int height) : 
     inner_data(width * height), 
     border_data(), 
     width(width), 
     height(height) 
    { 
    } 

    void Enlarge() 
    { 
     assert(border_data.empty()); // enlarge only once 
     border_data.resize((width + 2) * 2 + (height * 2)); 
     width += 2; 
     height += 2; 
    } 

    int Width() const 
    { 
     return width; 
    } 

    int Height() const 
    { 
     return height; 
    } 

    T& operator()(int x, int y) 
    { 
     assert(x >= 0); 
     assert(y >= 0); 
     assert(x < width); 
     assert(y < height); 

     if (border_data.empty()) 
     { 
      return inner_data[y * width + x]; 
     } 
     else 
     { 
      if (y == 0) 
      { 
       return border_data[x]; // top border 
      } 
      else if (y == height - 1) 
      { 
       return border_data[width + x]; // bottom border 
      } 
      else if (x == 0) 
      { 
       return border_data[width + height + y]; // left border 
      } 
      else if (x == width - 1) 
      { 
       return border_data[width * 2 + height * 2 + y]; // right border 
      } 
      else 
      { 
       return inner_data[(y - 1) * (width - 2) + (x - 1)]; // inner matrix 
      } 
     } 
    } 


private: 
    std::vector<T> inner_data; 
    std::vector<T> border_data; 
    int width; 
    int height; 
}; 

int main() 
{ 
    MyClass<int> test(2, 2); 

    test(0, 0) = 10; 
    test(1, 0) = 20; 
    test(0, 1) = 30; 
    test(1, 1) = 40; 

    for (auto y = 0; y < test.Height(); ++y) 
    { 
     for (auto x = 0; x < test.Width(); ++x) 
     { 
      std::cout << test(x, y) << '\t'; 
     } 
     std::cout << '\n'; 
    } 
    std::cout << '\n'; 

    test.Enlarge(); 

    test(2, 0) = 50; 
    test(1, 1) += 1; 
    test(3, 3) = 60; 

    for (auto y = 0; y < test.Height(); ++y) 
    { 
     for (auto x = 0; x < test.Width(); ++x) 
     { 
      std::cout << test(x, y) << '\t'; 
     } 
     std::cout << '\n'; 
    } 
} 

出力:

10  20 
30  40 

0  0  50  0 
0  11  20  0 
0  30  40  0 
0  0  0  60 

重要な点は、物理的な表現拡大された「アレイ」はもはや論理的なものと一致しない。

+0

それはそれを見る独創的な方法ですが、私はそのような解決策を見たことはないと思います。提案していただきありがとうございます! – Isuka

関連する問題