2012-03-25 7 views
1

行列やその他の多次元配列がCやC++で表現される方法や、それらを動的に割り当てる方法についてはまだ分かりません。私が正しく理解していれば、これはスタック上の整数のN×N行列を割り当て行列とC++での配列の配列とそれらの動的割り当て

int main() 
{ 
    int n; 
    cin >> n; 
    int a[n][n]; 
    ... 
} 

は、次のコードセグメントを考えてみましょう。 行列の(i、j)番目の要素には、[i] [j]を使用してアクセスできます。コンパイラ は、これを実際に割り当てられた1次元配列の(n * i + j)番目の要素へのアクセスに自動的に変換します。

スタックの の代わりに、n×nの行列aをヒープに割り当てたいとします。私は、次の操作を行うことができます

int main() 
{ 
    int n; 
    cin >> n; 
    int** a; 
    a = new int*[n]; 
    for (int i=0;i<n;i++) a[i] = new int[n]; 
    ... 
} 

私は今、[I] [J]として再び(i、j)は番目の要素にアクセスすることができます。しかし、実際にはn * n int、 にintにn個のポインタを加えてスペースを割り当てなければならなかったので、これは正確に と同じではありません。また、[i] [j]にアクセスすると、今度はメモリへのアクセスが2回しか発生せず、ただ1つの になります。一方、インデックス計算n * i + jは回避される。

ここで、mが小さい、例えばm = 2のm×nの行列に興味があるとします。 行ポインタの配列を使用すると、領域の33%が無駄になります。それを回避する方法はありますか? ?

もちろん、1次元配列を割り当ててインデックス演算を自分で行うことはできますが、 これは私にとって最高の解決策ではありません。

ご了承ください。自分で行くには良い方法です

インデックス数学をやって
int main() 
{ 
    int n; 
    cin >> n; 
    int *a; 
    a = new int[n*n]; 
} 

+0

は、私はそれをテストし、あなたの最初のコードは( '[N]の宣言で[N]') –

+0

を動作するはずわからないんだけど、それは作業を行います。私はまた、このようなn×nの行列を2つ割り当てようとしました。アドレスの違いは4(n * n + 1)です。これは、n * n intが実際に割り当てられていることを示しているようです。私はなぜ1が存在するのか分かりません。 – user1290928

+0

これは気にする必要はありません(コンパイラは、ローカルデータのアラインメントを強制するかもしれません)。 –

答えて

1

その後、むしろあなたがint型の1つの直線配列を割り当てますmat[n*i+j]

+0

はい、私はポストの終わりにその可能性を逃しました。他に選択肢はありませんか? – user1290928

1

を使用

int *mat = new int[n*n]; 

を行うことができます。

+0

私は私の質問の最後にそのオプションを述べました。私はインデックスの計算を自分でやってしまうことを避ける方法があるかどうかを知りたいのです。 – user1290928

0

コンパイラはあなたがコンパイル時にスタック上に必要となる正確なサイズを知る必要がありますので、あなたは

int n; 
cin >> n; 
int a[n][n]; 

を行うことはできません。これは、あなたが他のケースでは

#define N 10 
int a[N][N]; 

を行うことができます一方:-)実行時にそれを求めているとき、あなたは動的割り当てを使用する必要はできません。

Cの割り当ては、連続した1つのメモリを割り当てるのと同じように動作します。[i] [j]のようなインデックスは、そのメモリにジャンプする構文的な砂糖です。*(a + k * i + j)。ここで、kは内側の配列のサイズです。

+0

g ++コンパイラを使って上のコードをチェックしたところ、うまくいきました!あなたはそれを自分で確認するように求められています。 – user1290928

+0

ええと、私はそれをチェックアウトします... – tchap

+0

いずれにせよ。ご協力いただきありがとうございます! – user1290928

1

割り当て順序を逆にすることができます。「行」ポインタのために33%または何らかのメモリが使用されることに懸念がある場合は、列を列に変換するだけでなく、その逆にすることもできます。次に、[i][j]の代わりに、[j][i]という要素にアクセスします。もちろん、これはあなたの状況では実用的でないかもしれませんが、それ以上の情報なしで言うのは難しいです。

しかし、実際にはインデックスの計算に問題はなく、本質的に間違っていることはありません。

+0

インデックスの順序を逆にするとよいでしょう。動的な設定で問題が完全に解決されない場合があります。行が増えたり、列が増えたりすることがあります。また、2×2の行列をたくさん保存したい場合は、いずれの場合も空間の33%が無駄になります。 – user1290928

+0

ご協力いただきありがとうございました! – user1290928

+0

もちろん、インデックスの算術を自分でやることについて倫理的に間違っていることはありません。明らかに、私のためにコンパイラに要求する人はいません。 – user1290928

1

あなたが好きではない場合は、インデックスの計算を行ったクラスを作成することができます。

class Matrix 
{ 
    public: 
     Matrix(int iRows, int iCols) 
     : mRows(iRows), mCols(iCols), m(new int[mRows*mCols]) { } 
     ~Matrix() { delete [] m; } 

     int &element(int iRow, int iCol) { return m[iRow * mCols + iCol]; } 

     int mRows, mCols, *m; 
}; 
+0

提案していただきありがとうございます。そのようなクラスを定義することは本当に必要ですか?私が描写している状況のためのサポートが組み込まれていませんか? – user1290928

+0

ええと...私は本当にそれをあまり考えなかった。私は数学をするのに慣れています。それは本当に不便ですか? –

+0

私が考えることができる最高のマクロを使用することですか? #define ndx(r、c、n)(n * r + c) –

関連する問題