
КЭкзCPP / MultiDimArray
.doc
Многомерные массивы
Многомерные массивы – совокупность однотипных элементов, упорядоченных с помощью системы индексов, для каждого измерения указывается размер.
Например,
const int n=5, m=6;
int a[n][m]; //это можно рассматривать как массив из 5-ти элементов, каждый из которых есть массив из 6-ти целых элементов, т.е. вектор из 5-ти векторов, ещё говорят - матрица 5*6.
В памяти такой массив располагается в последовательных полях построчно
a[0][0] |
. . |
a[0][5] |
a[1][0] |
… |
… |
a[1][5] |
… |
a[4][0] |
… |
a[4][5] |
float b[3][5][4];//-массив 3-х мерный : 3 матрицы 5*4
Элементы 1 матрицы |
Элементы 2 матрицы |
Элементы 3 матрицы |
Правило размещения : элементы многомерного массива располагаются в таком порядке, что у них быстрее всего меняется последний индекс:
b[0][0][0], b[0][0][1] ,b[0][0][2], b[0][0][3], b[0][1][0],
b[0][1][1], b[0][1][2], b[0][1][3],…
Для type a[n][m];
Адрес( a[i][j])= Адрес(a)+(i*m + j)*sizeof( type ), т.е.
для вычисления адресного выражения a[i][j] транслятору необходимо знать второй размер m, а не первый n.
Связь между массивами и указателями распространяется и на двумерные массивы. a[i][j] означает то же самое, что *(*(a+i)+j):
a[i]-рассматривается транслятором как имя одномерного массива из m элементов
(адрес начала i-той строки), т.е. это указатель i-той строки
a[i][j] = *(a[i]+j) = *(*(a+i)+j).
(в соответствии с арифметикой указателей). Все следующие выражения правильны и обозначают одно и то же
a[i][j] *(a[i]+j) (*(a+i))[j]
Инициализация многомерного массива:
int x[][]={{1,1},{2,1},{0,1}}; //3 строки по 2 элемента в строке.
int x[3][2]={1,1,2,1,0,1};// элементы по строкам
Передача многомерного массива в функцию
При описании массива его максимальные размеры задаются константами, а при передаче его в функцию часто используются размеры меньшие максимальных.
При передаче массива в функцию все размеры, если они не известны на этапе компиляции (т.е. не совпадают с максимальными) должны передаваться в качестве параметров.
Параметр – многомерный массив можно оформить так (например, для двумерного массива):
тип имя [n][m],
Из формулы для адреса элемента массива видно, что первый размер n транслятору не нужен, а второй m нужен (он задает кол-во элементов в строке), поэтому параметр массив двумерный будет выглядеть так: тип имя [][m].
Аналогично 3-х мерный: тип имя [][m][k].
Здесь m, k – размеры, заданные при описании.
//Property_matr.cpp
#include <iostream>
using namespace std;
// Проверка свойств матриц
const int n=6;
void rdmm(int& k,int a[][n]);
bool simm(int k,int a[][n]);
int main ()
{ int k,L=0,c;
int a [n][n];
do
{rdmm(k,a);
if (simm (k,a)){cout<<"\n simmetr";L++;}
cout<< "echo? (1-yes,0-no)";
cin>>c;
}
while (c!=0);
if (L==0) {cout<<"\n no matrix";}
return 0;
}
void rdmm(int& k,int a[][n])
{int i,j;
// чтение матрицы
cout<<"\n razmer <= "<<n;
cin>>k;
cout<<"\n el-ti \n";
for(i=0;i<k;i++)
for (j=0; j<k;j++)
cin>>a[i][j];
}
bool simm(int k,int a[][n])
{// проверка , явл. ли матрица симметрической.
int i,j;
bool p;
i=0; p=true;
while ((i<k-1)&& p)
{j=i+1;
while ((j<k)&& p)
{p=(a[i][j]==a[j][i]);
j++;
}
i++;
}
return p;
}
Создание динамической матрицы
int n,m;
cout<<"vvedite n,m ";
cin>>n>>m;
//лучше всего такой способ создания динамической матрицы:
int **q= new int * [n];
for(int i=0;i<n;i++)
q[i]=new int [m];
//заполнение матрицы
for(int i=0;i<n;i++)
{for (int j=0;j<m;j++)
{q[i][j]=j*10+i;
//cout<<setw(5)<<q[i][j];
}
cout<<'\n';}
for(int i=0;i<n;i++){delete[]q[i];}
delete []q;
return 0;
}
Рассмотрим два различных определения
int *massiv[4]; //массив указателей на объекты типа int
int (*ptr)[4]; //указатель ptr на массив из 4 элементов, каждый из которых – int
Далее возможно выделить память, например,
ptr=new int [3][4];
delete [] ptr;
ptr – не имя массива, а переменная, позволяющая перемещаться по массива элементам, значение этого указателя определяется при выделении памяти – new.
Можно, случайно забыть (потерять) адрес первого элемента массива.
Благодаря массиву указателей можно более эффективно расходовать память…
Например,
«Обычное» выделение памяти -
char list[][30] = {“rectangle”, ”circle”, ”segment”};
«рациональное» -
char *pointer [] = {“rectangle”, ”circle”, ”segment”};
Пример перестановки указателей на одномерные массивы
void main()
{ const int n=5;
const int m=7;
double array [n][m];
for(int i=0; i<n; i++)
for(int j=0;j<m;j++)
array[i][j]=n-i;
double *par[n];
for(int i=0;i<n;i++)
par[i]=(double *)&array[i];
cout<<endl;
for(int i=0; i<n; i++)
{cout<<endl;
for(int j=0;j<m;j++)
cout<<"\t"<<par[i][j];
}
double si,sk;
for(int i=0; i<n-1; i++)
{ si=0.0;
for(int j=0; j<m; j++)
si+=par[i][j];
for(int k=i+1; k<n; k++)
{ sk=0.0;
for(int j=0; j<m; j++)
sk+=par[k][j];
if(si>sk)
{ double* pa = par[i];
par[i]=par[k]; par[k]=pa;
double a = si; si=sk; sk= a;
}
}
}
cout<<endl;
for(int i=0; i<n; i++)
{cout<<endl;
for(int j=0;j<m;j++)
cout<<"\t"<<par[i][j];
}
}