Массивы, обработка элементов массива

Представьте себе такую задачу. Вам нужно хранить в памяти компьютера значения линейной функции  при . Как это сделать? Мы умеем создавать отдельные переменные, но тогда здесь нам понадобится 100 переменных, с которыми надо будет еще как-то управляться. Но, к счастью, все можно сделать гораздо проще. Можно задать массив из 100 элементов и в каждый элемент массива записать значение функции при конкретном значении x.

Итак, чтобы задать массив в языке Java используется такой синтаксис:

<тип данных> <имя массива>[];
<тип данных>[] <имя массива>;

Например, в нашем случае следует выбрать вещественный тип данных для элементов массива. Имя массива обозначим как и функцию y:

float y[];

и далее можем создать массив со 100 элементами с помощью оператора new:

y = new float[100];

Эти две строчки можно объединить в одну и записать все так:

float y[] = new float[100];

Все, мы создали массив. Теперь, чтобы в его первый элемент записать первое значение функции, используется такой синтаксис:

y[0] = k*0+b;

Здесь k, b – переменные с какими-либо значениями, а x=0. Обратите внимание, первый элемент массива всегда имеет индекс, равный нулю. По аналогии, записывается значение во второй элемент массива:

y[1] = k*1+b;

и так далее. Давайте напишем целиком программу, которая заносит все 100 значений в массив и выводит их на экран.

float y[] = new float[100];
float k = 0.5f, b = 2.0f;
 
for (int x = 0; x < 100; ++x)
    y[x] = k * x + b;
 
for (int x = 0; x < 100; ++x)
    System.out.print(y[x] + " ");

Обратите внимание, если мы хотим прочитать значение из массива, то достаточно просто обратиться к нему по соответствующему индексу, например, так:

float a = y[5];

В результате переменная a будет равна 6-му значению элемента массива y. Поэтому, когда мы пишем

System.out.print(y[x]);

то осуществляется вывод элемента массива с индексом x. Вот так можно записывать и считывать значения из массива.

В языке Java можно сразу инициализировать массив конкретными значениями в момент его объявления, например, так:

int powers[] = new int[] {1, 2, 4, 6};

или так:

int powers[] = {1, 2, 4, 6};

В этом случае элементу powers[0] присваивается значение 1, powers[1] – 2, и т.д. Обратите внимание, что в этом случае нигде не должен указываться размер массива. Его размер определяется числом инициализируемых элементов.

Выведем этот массив в консоль:

for (int x = 0; x < powers.length; ++x)
    System.out.print(powers[x] + " ");

Смотрите, здесь для определения числа элементов в массиве использовалось его свойство length. То есть, индекс последнего элемента в массиве всегда равен length-1. Например, вывести только последний элемент нашего массива можно так:

System.out.println(powers[powers.length-1]);

Для хранения некоторых видов информации, например, изображений удобно пользоваться двумерными массивами. Объявление двумерных массивов осуществляется следующим образом:

int ar2D[][] = new int[3][4];
int array2D[][] = { { 0, 1, 2 }, { 3, 4, 5 } };

Какой индекс здесь считать строками, а какой – столбцами, решает сам программист, компьютер все равно будет обрабатывать элементы этого массива в соответствии с программой и что такое строки и столбцы ему неведомо.

Здесь также, первый элемент массива имеет индексы 0, то есть,

array2D[0][0] = 1;        //в первый элемент записано число 1

а далее, уже так:

array2D[0][1] = 2;
array2D[1][0] = 3;

и так далее. Давайте в качестве примера напишем программу, которая бы записывала в массив E размерностью 10x10 такие значения:

final int N = 10;
int E[][] = new int[N][N];
 
for(int i = 0;i < N;++i)
    for(int j = 0;j < N;++j)
        if(i == j) E[i][j] = 1; else E[i][j] = 0;
 
for (int i = 0; i < N; ++i) {
    for (int j = 0; j < N; ++j)
        System.out.print(E[i][j]+" ");
 
    System.out.print("\n");
}

Также в Java можно создавать так называемые многомерные зубчатые массивы. Визуально такой двумерный массив можно представить вот в таком виде:

А задать его можно так:

short z[][] = new short[5][];
z[0] = new short[3];
z[1] = new short[4];
z[2] = new short[2];
z[3] = new short[3];
z[4] = new short[1];

Для обработки элементов такого массива можно записать такие циклы:

short cnt = 1;
for(int i = 0;i < z.length;++i)
    for(int j = 0;j < z[i].length;++j) {
        z[i][j] = cnt;
        cnt++;
    }
 
for(int i = 0;i < z.length;++i) {
    for (short val : z[i])
        System.out.print(val + " ");
 
    System.out.print("\n");
}

Смотрите, что здесь получается. Вот это свойство z.length возвращает первую размерность массива, то есть 5. Далее, мы берем i-ю строку (либо столбец в зависимости от интерпретации) и узнаем сколько элементов в этой строке. И внутри второго цикла записываем туда значение cnt, которое постоянно увеличивается на 1.

Затем, мы выводим полученный массив в консоль. Здесь также сначала перебираем первую его размерность. А вот этот цикл перебирает по порядку все элементы i-й строки и помещает их в переменную val. Обратите внимание на его синтаксис:

for(<тип данных> : <коллекция>) { тело цикла }

Вот так можно перебирать элементы любой коллекции, в данном случае строки массива. Вот так все это работает. По аналогии можно задавать массивы любой размерности.

Обработка элементов массива

Существует несколько стандартных алгоритмов обработки элементов массива:

  1. Удаление значения из массива по определенному индексу.
  2. Вставка значения в массив по определенному индексу.
  3. Сортировка элементов массива.

Начнем с первого – удаления элемента из массива. Создадим вот такой массив:

final int N = 9;
short a[] = new short[N];

запишем туда значения с 1 по 9:

for(int i=0;i < N;++i) a[i] = (short)(i+1);

Теперь удалим элемент со значением 6. Для этого нужно проделать такую операцию:

Причем, сначала перемещаем 7-ку на место 6-ку, затем 8-ку и 9-ку, то есть, двигаемся от удаляемого элемента к концу массива. Программа будет выглядеть так:

final int N = 9;
short a[] = new short[N];
 
for(int i=0;i < N;++i) a[i] = (short)(i+1);
 
for (int i = 5; i < N-1; ++i)
    a[i] = a[i + 1];
 
for (short val : a) System.out.print(val+" ");

Здесь мы начали движение с 5-го индекса (то есть 6-го элемента массива) и на первой итерации делаем операцию a[5]=a[6], то есть, 7-ку ставим на место 6-ки. На следующей итерации уже имеем a[6]=a[7] – перемещаем 8-ку и, затем, a[7]=a[8] – перемещаем 9-ку. Все, в итоге значение 6 было удалено из массива.

Теперь реализуем второй алгоритм и вставим значение 4, которого не хватает вот в таком массиве:

short a[] = new short[] {1, 2, 3, 5, 6, 7, 8, 9, 9};

Здесь в конце записаны две 9, чтобы мы могли сдвинуть все элементы на 1 вправо и вставить элемент со значением 4. То есть, нам следует выполнить такую операцию над элементами массива:

Обратите внимание, что сдвиг осуществляется с конца массива. Если мы начнем это делать с 4-го, то просто затрем все остальные значения пятеркой. Итак, вот программа, которая вставляет 4-ку в этот массив:

short a[] = new short[] {1, 2, 3, 5, 6, 7, 8, 9, 9};
 
for (int i = 8; i > 3; --i)
 
    a[i] = a[i - 1];
 
a[3] = 4;
 
for (short val : a) System.out.print(val+" ");

Здесь счетчик i в цикле сначала равен 8 – это индекс последнего элемента нашего массива. Затем, делается операция a[i]=a[i-1], то есть, a[8]=a[7]. Таким образом, мы присваиваем 8-му элементу значение 7-го элемента. Это и есть смещение значения вправо. На следующей итерации i уменьшается на 1, то есть, равно 7 и операция повторяется: a[7]=a[6] и так далее, последний смещаемый элемент будет: a[4]=a[3]. После этого i будет равно 3, условие цикла становится ложным и он завершается. После смещения, мы присваиваем 4-му элементу массива значение 4 и выводим получившийся массив на экран.

Теперь рассмотрим довольно распространенный алгоритм сортировки элементов массива по методу всплывающего пузырька. Реализуем его на языке Java.

byte a[] = {3, 5, 1, 6, 2, 4};
 
for (int i = 0; i < a.length-1; ++i) {
    byte min = a[i];
    int pos = i;
 
    for (int j = i + 1; j < a.length; ++j)
        if (min > a[j]) {
            pos = j;
            min = a[j];
        }
 
    byte t = a[i];
    a[i] = a[pos];
    a[pos] = t;
}
 
for (short val : a) System.out.print(val+" ");

Здесь первый цикл показывает с какого элемента искать минимальный, то есть, это местоположение той вертикальной черты в методе всплывающего пузырька. Затем, задаем две вспомогательные переменные min – минимальное найденное значение, pos – индекс минимального элемента в массиве. Второй вложенный цикл перебирает все последующие элементы массива и сравнивает его с текущим минимальным и если будет найдено меньшее значение, то min становится равной ему и запоминается его позиция. Вот эти три строчки меняют местами текущее значение элемента с найденным минимальным, используя вспомогательную переменную t. И в конце программы выполняется вывод элементов массива на экран.

Запустим эту программу и посмотрим как она работает. Кстати, если мы теперь хотим выполнить сортировку по убыванию, то достаточно изменить вот этот знак на противоположный.