2次元配列にデータを格納する場合、2種類の格納の仕方があります。
それは、縦からデータを格納するかor横からデータを格納するかです。
本記事では、縦からデータを格納する方法を列優先とし、
横からデータを格納する方法を行優先とよぶことにします。
データ格納順
プログラミング言語によって記法は異なりますが、2次元配列を用意する場合、
array(x,y)となり、xは縦(行)の大きさ、yは横(列)の大きさになります。
また2次元配列array(2,3)とした場合、以下のようになります。
array(0,0) | array(0,1) | array(0,2) |
array(1,0) | array(1,1) | array(1,2) |
この配列に対して、データがメモリ上から割り当てられるのですが、
ここで、データの格納の仕方が先ほど述べたように2種類になります。
1次元目から動くもの(列優先)
array(0,0) |
array(1,0) |
array(0,1) |
array(1,1) |
array(0,2) |
array(1,2) |
↓
↓
↓
↓
↓
2次元目から動くもの(行優先)
array(0,0) |
array(0,1) |
array(0,2) |
array(1,0) |
array(1,1) |
array(1,2) |
↓
↓
↓
↓
↓
arrayの値を1から6まで1ずつ増える場合、
1次元から動くもの(列優先)
1 | 3 | 5 |
2 | 4 | 6 |
2次元目から動くもの(行優先)
1 | 2 | 3 |
4 | 5 | 6 |
となります。
配列を行列としてみた場合、縦(行)と横(列)が同じ(正方行列)ときは、転置行列となります。
プログラミング言語の列優先と行優先
説明した列優先と行優先ですが、プログラミング言語によって違います。
データ格納順を可視化するプログラムを書き、実行してみましょう。
本記事では、インタプリタ言語であるPython、Julia、コンパイラ言語であるC++、Fortranで比較します。
データ格納順を可視化するプログラムですが、差1の等差数列である2×3の2次元配列にして、インデックスとともに値を出力しています。
Python
import numpy as np
if __name__ == '__main__':
ivar = np.arange( 1,7, dtype='int')
ivar = ivar.reshape(2,3)
for i in range(2) :
for j in range(3):
print('ivar[%1d][%1d] is the %dth order' % (i, j, ivar[i][j] ))
実行例:
$ python rcm.py
ivar[0][0] is the 1th order
ivar[0][1] is the 2th order
ivar[0][2] is the 3th order
ivar[1][0] is the 4th order
ivar[1][1] is the 5th order
ivar[1][2] is the 6th order
2次元目から動いていることが分かると思います。
以上の事から行優先になります。
Julia
using Printf
ivar = reshape(1:6,(2,3))
for j = 1:3
for i = 1:2
@printf("ivar[%1d][%1d] is the %dth order\n",i-1,j-1,ivar[i,j])
end
end
実行例:
$ julia rcm.jl
ivar[0][0] is the 1th order
ivar[1][0] is the 2th order
ivar[0][1] is the 3th order
ivar[1][1] is the 4th order
ivar[0][2] is the 5th order
ivar[1][2] is the 6th order
1次元目から動いていることが分かると思います。
以上の事から列優先になります。
C++
#include <bits/stdc++.h>
using namespace std;
int main(){
vector<vector<int>> ivar =
{
{1,2,3},
{4,5,6},
};
for (int i = 0; i < 2; i++){
for (int j = 0; j < 3; j++){
cout << "ivar["<< i << "][" << j \
<< "] is the " << ivar.at(i).at(j) << "th order" << endl;
}
}
return 0;
}
実行例:
$ g++ rcm.cpp
$./a.out
ivar[0][0] is the 1th order
ivar[0][1] is the 2th order
ivar[0][2] is the 3th order
ivar[1][0] is the 4th order
ivar[1][1] is the 5th order
ivar[1][2] is the 6th order
2次元目から動いていることが分かると思います。
以上の事から行優先になります。
Fortran
implicit none
integer::ivar(2,3),i,j
ivar = reshape((/1,2,3,4,5,6/),(/2,3/))
do j=1,3
do i =1,2
write(*,'(a,i1,a,i1,a,i1,a)')"ivar[",i-1,"][",j-1,"] is the ",ivar(i,j),"th order"
enddo
enddo
end program
実行例:
$ gfortran rcm.f90
$./a.out
ivar[0][0] is the 1th order
ivar[1][0] is the 2th order
ivar[0][1] is the 3th order
ivar[1][1] is the 4th order
ivar[0][2] is the 5th order
ivar[1][2] is the 6th order
1次元目から動いていることが分かると思います。
以上の事から列優先になります。
まとめ
データ格納順は、プログラミング言語によって異なる。
1次元目が先に動く(行変動、列固定)場合、列優先
Fortran、Juliaなどが該当
2次元目が先に動く(行固定、列変動)場合、行優先
Python、C、C++などが該当