Нерегулярні масиви. Виділення пам’яті. N-вимірні нерегулярні масиви. Переваги використання нерегулярних масивів. Приклади

Нерегулярні масиви. Виділення пам’яті. N-вимірні нерегулярні масиви. Переваги використання нерегулярних масивів. Приклади


Зміст


1. Що таке нерегулярні масиви? Характерні риси нерегулярних масивів. Приклади оголошення нерегулярних масивів

Нерегулярні масиви – це різновид n-вимірних (n>1) масивів, які представлені як масиви одновимірних масивів з різною кількістю елементів.

У нерегулярному масиві розмір одновимірних масивів, що відповідають останньому виміру, є плаваючим. Пам’ять для таких одновимірних масивів виділяється різного розміру.

При оголошенні нерегулярного масиву, щонайменше один вимір не містить конкретного значення (пусті квадратні дужки [ ]).

Наприклад, нижче наводяться приклади оголошень різних видів нерегулярних масивів

// оголошення регулярних та нерегулярних масивів
int[][] A = new int[3][5]; // регулярний масив
int[][] B = new int[3][]; // нерегулярний двовимірний масив
int[][][] C = new int[3][4][]; // нерегулярний тривимірний масив
int[][][] D = new int[3][][]; // нерегулярний тривимірний масив
// int[][][] E = new int[][][]; // помилка, так не можна

У вищенаведеному прикладі оголошується один регулярний (A) та три нерегулярні (B, C, D) масиви.

2. Яка відмінність між нерегулярними масивами та регулярними масивами? Приклад

У регулярному масиві кількість елементів у кожному вимірі є відома. Ця кількість задається при виділенні пам’яті для масиву оператором new.

У нерегулярному масиві кількість елементів щонайменше в одному вимірі є невідомою. Ця кількість для усього виміру може відрізнятись.

Наприклад. Нехай оголошено регулярний масив A, для якого виділена пам’ять

int[][] A = new int[3][5]; // регулярний масив, кількість елементів = 3*5 = 15

У цьому масиві кількість елементів відома при виділенні пам’яті оператором new.

У випадку, коли оголошено нерегулярний масив

int[][] B = new int[3][]; // нерегулярний масив, загальна кількість елементів невідома

то відомо, що цей масив B містить 3 одновимірні масиви. Кількість елементів у кожному з цих масивів невідома. Це є ознакою оголошення нерегулярного масиву. Щоб сформувати ці 3 одновимірні масиви, можна написати, наприклад, такий код

// виділення пам'яті для масиву B
for (int i=0; i<3; i++)
  B[i] = new int [i*2+1];

// заповнення масиву B значеннями
for (int i=0; i<3; i++)
  for (int j=0; j<B[i].length; j++)
    B[i][j] = i*3+j;

У вищенаведеному коді спочатку виділяється пам’ять для кожного з 3-х одновимірних масивів: B[0], B[1], B[2]. Довжина масиву B[0] становить 1. Довжина масиву B[1] рівна 3. Довжина масиву B[2] рівна 5. Щоб визначити довжину масиву, використовується властивість length

int t;
t = B[0].length; // t = 1
t = B[1].length; // t = 3
t = B[2].length; // t = 5

Після такого коду, кількість елементів в нерегулярному масиві буде рівна 1+3+5 = 9.

3. Які переваги використання нерегулярних масивів?

Використання нерегулярних масивів дає наступні переваги:

  • у деяких випадках суттєво економиться пам’ять, якщо в масиві є велика кількість невикористаних елементів. Особливо це важливо, якщо елементами нерегулярного масиву є об’єкти (екземпляри) класів, що займають багато пам’яті;
  • встановлення різної контрольованої довжини кожного одновимірного масиву, у деяких випадках може краще відображати зміст розв’язку поставленої задачі.



4. Чи можуть нерегулярні масиви бути трьохвимірними, чотирьохвимірними і більше?

Так, можуть.

Наприклад. Оголошується та використовується тривимірний нерегулярний масив C.

int[][][] C = new int[3][4][]; // нерегулярний тривимірний масив

// створення нерегулярного масиву C
// виділення пам'яті для масиву C
for (int i=0; i<3; i++)
  for (int j=0; j<4; j++)
    C[i][j] = new int[(i+1)*(j+1)]; // пам'ять виділяється нерегулярно

// заповнення масиву C значеннями
for (int i=0; i<3; i++)
  for (int j=0; j<4; j++)
    for (int k=0; k<C[i][j].length; k++)
      C[i][j][k]=i+j+k;

int t;

// перевірка
t = C[0][1][1]; // t = 2

5. Скільки вимірів можуть мати нерегулярні масиви?

Нерегулярні масиви можуть мати два і більше вимірів. Найпоширеніші це двовимірні нерегулярні масиви. Однак, допускається оголошення нерегулярних масивів з будь-якою кількістю вимірів. Головне, щоб перший (верхній) вимір мав значення. Інакше, компілятор видасть помилку.

6. Приклад оголошення та використання двовимірного нерегулярного масиву типу int

У прикладі оголошується та використовується нерегулярний двовимірний масив з іменем B. Масив містить 3 одновимірні масиви розміри яких не співпадають.

// оголошення нерегулярного масиву B
int[][] B = new int[3][]; // нерегулярний двовимірний масив

// виділення пам'яті для масиву B
for (int i=0; i<3; i++)
  B[i] = new int [i*2+1];

// заповнення масиву B значеннями
for (int i=0; i<3; i++)
  for (int j=0; j<B[i].length; j++)
    B[i][j] = i*3+j;

int t;

// читання значень елементів масиву B
t = B[0].length; // t = 1
t = B[1].length; // t = 3
t = B[2].length; // t = 5
t = B[0][0]; // t = 0
t = B[1][0]; // t = 3
t = B[1][1]; // t = 4

7. Приклад оголошення та використання двовимірного нерегулярного масиву об’єктів (екземплярів) класу

Оголошується двовимірний нерегулярний масив об’єктів класу WorkDay. Клас WorkDay містить інформацію про відроблені години деяким працівником та тариф.

Також оголошується клас WorkYear, що містить масив об’єктів WD типу WokrDay, який згрупований за місяцями року. Масив WD є нерегульований і містить 12 одновимірних масивів, кожен з яких відповідає місяцю року. Кожен одновимірний масив має стільки днів, скільки днів у відповідному місяці року.

// клас, що описує один робочий день
class WorkDay {
  int hours; // кількість відроблених годин
  double tariff; // розцінка за годину

  // конструктор класу
  WorkDay(int hours, double tariff) {
    this.hours = hours;
    this.tariff = tariff;
  }
}

// клас, що описує робочий рік для деякого працівника
class WorkYear {
  // масив типу WorkDay, розбитий по місяцях року
  WorkDay[][] WD = new WorkDay[12][]; // нерегулярний масив об'єктів типу WorkDay

  // конструктор
  WorkYear() {

  // у конструкторі виділяється пам'ять для нерегулярного масиву об'єктів
  WD[0] = new WorkDay[31]; // січень - 31 день
  WD[1] = new WorkDay[29]; // лютий - 29 (28) днів
  WD[2] = new WorkDay[31]; // березень - 31 день
  WD[3] = new WorkDay[30]; // квітень - 30 днів
  WD[4] = new WorkDay[31]; // травень
  WD[5] = new WorkDay[30]; // червень
  WD[6] = new WorkDay[31]; // липень
  WD[7] = new WorkDay[31]; // серпень
  WD[8] = new WorkDay[30]; // вересень
  WD[9] = new WorkDay[31]; // жовтень
  WD[10] = new WorkDay[30]; // листопад
  WD[11] = new WorkDay[31]; // грудень

  // обов'язково потрібно виділити пам'ять для кожного об'єкту через конструктор
  for (int i=0; i<WD.length; i++)
    for (int j=0; j<WD[i].length; j++)
      WD[i][j] = new WorkDay(0, 0.0); // виклик конструктора
  }
}

Використання нерегульованого масиву WD класу WorkYear може бути таким

// використання нерегульованого масиву WD класу WorkYear
WorkYear WY = new WorkYear();
int nDays; // к-сть днів у місяці

// перевірка
nDays = WY.WD[5].length; // nDays = 30

// заповнення довільного елементу масиву WY
WY.WD[0][0].hours = 6; // 1 січня
WY.WD[0][0].tariff = 200.00; // тариф = 200.00 грошових одиниць
WY.WD[3][0].hours = 7; // 1 квітня
WY.WD[3][0].tariff = 130.00;

8. Приклад оголошення та використання тривимірного нерегулярного масиву типу double

У прикладі оголошується клас DoubleArray, що містить тривимірний нерегулярний масив D типу double. Виділення пам’яті та заповнення значеннями елементів масиву D реалізується в конструкторі класу.

// клас, що містить тривимірний нерегульований масив типу double
class DoubleArray {
  // оголошення тривимірного нерегулярного масиву типу double
  double[][][] D = new double[2][3][];

  // конструктор
  DoubleArray()
  {
    // виділення пам'яті для нерегулярного масиву D[2][3][]
    D[0][0] = new double[5];
    D[0][1] = new double[6];
    D[0][2] = new double[3];
    D[1][0] = new double[4];
    D[1][1] = new double[5];
    D[1][2] = new double[7];

    // заповнення елементів масиву довільними значеннями
    for (int i=0; i<D.length; i++)
      for (int j=0; j<D[i].length; j++)
        for (int k=0; k<D[i][j].length; k++)
          D[i][j][k] = i + j + k*0.25;
  }
}

Нижче демонструється використання класу DoubleArray

// використання нерегульованого масиву D класу DoubleArray
DoubleArray da = new DoubleArray();
double x;
x = da.D[0][1][2]; // x = 1.5
x = da.D[1][0][3]; // x = 1.75
x = da.D[1][2][5]; // x = 4.25

9. Приклад оголошення та використання тривимірного масиву цілих чисел, в якому два виміри мають змінну кількість елементів

Оголошується та використовується тривимірний масив D, в якому у двох вимірах не вказується кількість елементів.

// у масиві D у 2-му і 3-му вимірах не вказується кількість елементів
int[][][] D = new int[3][][]; // нерегулярний тривимірний масив

// int[][][] E = new int[][][]; // помилка, так не можна
// формування масиву D
// виділення довільного розміру пам'яті для 2-го виміру

for (int i=0; i<D.length; i++) // D.length = 3
  D[i] = new int[i+2][];

// виділення довільного розміру пам'яті для 3-го виміру
for (int i=0; i<D.length; i++)
  for (int j=0; j<D[i].length; j++)
    D[i][j] = new int [(i+2)*(j+1)];

// заповнення масиву D значеннями
for (int i=0; i<D.length; i++)
  for (int j=0; j<D[i].length; j++)
    for (int k=0; k<D[i][j].length; k++)
      D[i][j][k] = i+j*(k+2);

// можна й так
D[0][0][1] = 23;
D[1][2][2] = 230;

int t;

// використання масиву D
t = D[0][1][2]; // t = 4
t = D.length; // t = 3
t = D[0].length; // t = 2
t = D[1].length; // t = 3
t = D[2].length; // t = 4
t = D[0][1].length; // t = 4
t = D[1][2].length; // t = 9

10. Приклад оголошення та використання тривимірного нерегульованого масиву об’єктів (екземплярів) класу

Нехай задано деякий клас з іменем A. У класі реалізовано внутрішню змінну a цілого типу та конструктор класу. Даний приклад демонструє виділення пам’яті, заповнення значеннями та використання тривимірного нерегульованого масиву об’єктів класу A.

// деякий клас A
class A {
  int a;

  // конструктор класу
  A(int a) {
    this.a = a;
  }
}

Нижченаведений код може служити прикладом для роботи з тривимірним масивом об’єктів

// використання тривимірного нерегульованого масиву об'єктів класу A
int n = 4;
A[][][] objA = new A[n][][]; // оголосити об'єкт objA з нерегульованим масивом

// виділити пам'ять для нерегульованого масиву елементів 2-го виміру
for (int i=0; i<objA.length; i++)
  objA[i] = new A[i+2][]; // деяка формула

// виділити пам'ять для нерегульованого масиву елементів 3-го виміру
for (int i=0; i<objA.length; i++)
  for (int j=0; j<objA[i].length; j++)
    objA[i][j] = new A[i+j+2];

// виділити пам'ять для об'єктів класу A
for (int i=0; i<objA.length; i++)
  for (int j=0; j<objA[i].length; j++)
    for (int k=0; k<objA[i][j].length; k++)
      objA[i][j][k] = new A(i+2*j+3*k); // виклик конструктора

// перевірка
int t;
t = objA[0][1][2].a; // t = 8
t = objA[0][1][1].a; // t = 5


Зв’язані теми