バッファのように機能する整数行列があります。
x = {{0, 0, 0, 0, 0}, {1, 1, 1, 1, 1}, {2, 2, 2, 2, 2}};
新しい行を追加する{3, 3, 3, 3, 3}
と、新しいマトリックスは次のようになります。
x = {{1, 1, 1, 1, 1}, {2, 2, 2, 2, 2}, {3, 3, 3, 3, 3}};
すべての要素をコピーせずにこれを行う賢い方法はありますか?
行列が として定義されていて、int **
各行を個別に割り当てる場合、行ポインターを交換するだけで済みます。
モジュロ演算はどうですか?
要素にアクセスすると、次のmatrix[x + SZ * y]
ように変更できます。
matrix[x + SZ * ((y + FIRST_ROW) % SZ)]
.
このシフトを実装するには、新しい行 {0, 0, 0} があった場所に新しい行 {3, 3, 3..} を配置し、FIRST_ROW
カウンターをインクリメントして新しい開始行を指すようにします。
(通常の2次元配列ではなく)配列へのポインターの配列を使用する場合、すべての要素をコピーする代わりに、行へのポインターのみをコピーできます。
また、ポインタの配列を全体的に割り当てることに問題がない場合は、新しいポインタを最後に追加して、ポインタを配列の「開始」に進めることができます。しかし、この種のシフトを何度も実行したい場合は、これは良い考えではありません。そしてもちろん、リソースを適切に使用できるように、元のポインタがどこかにあることを確認する必要がありfree()
ます。
コード例を書くのが面倒 - モジュロ演算を使用して行をアドレス指定できます。新しい行をプッシュするときは、単に開始オフセット変数を増やし、マトリックスの高さを追加し、結果をマトリックスの高さでモジュロします。このようにして、行列全体をコピーする必要がなく、行列配列をコンパクトに保つ循環行列を取得します。
リンクされたリストを使用します。
struct node
{
int row[5];
struct node *next;
};
行の追加は、リストを最後までたどり、NULL ネクスト ポインターを新しいノード (ネクスト ポインターが NULL) に置き換えるのと同じくらい簡単です。
2 番目の行を指すようにインクリメントx
してから、最初の行を解放できますか? 明らかに、一度に行を割り当てる必要がありますが、これは行列が連続していることを保証しません。それが必要な場合は、行列を保持するためにメモリの 1 つの大きなブロックを割り当て、最後に到達したときに未使用の部分を上書きすることができます。