Рекурсия, итерация и оценки сложности алгоритмов
Массивы в языке Java
Язык Java, так же как и многие другие языки, позволяет работать с массивами элементов различных типов. Массив (array) используют, когда возникает необходимость хранить несколько однотипных значений, например, 50 целых чисел или 100 наименований книг, так как было бы неудобно использовать в таких случаях различные имена для всех этих переменных. В ближайшее время мы будем работать только с одномерными массивами и не будем пользоваться тем, что массивы — динамические структуры данных. Об этом речь пойдет в третьей главе книги.
Рассмотрим следующую простейшую задачу на работу с массивом целых чисел.
Задача 5.6. Напишите программу, которая вводит с клавиатуры непустой массив целых чисел, печатает его, затем инвертирует (то есть меняет местами первый элемент с последним, второй — с предпоследним и т.д.), и вновь печатает.
Текст программы
public class InvArr {
public static void main(String[] args) throws Exception {
int n, i, a[];
n = Xterm.inputInt("Введите длину массива n -> ");
a = new int[n];
for (i=0; i<n; i++)
a[i] = Xterm.inputInt("Введите a[" + i + "] -> ");
Xterm.print("Введенный массив a =");
for (i=0; i<n; i++)
Xterm.print(" " + a[i]);
Xterm.print("\nИнвертированный массив a =");
for (i=0; i<n/2; i++) {
int j = a[i]; a[i] = a[n-1-i]; a[n-1-i] = j;
}
for (i=0; i<n; i++)
Xterm.print(" " + a[i]);
Xterm.print("\n");
}
}Как видно из текста этой программы, для того чтобы завести массив, необходимо объявить его и зарезервировать затем память для его элементов с помощью оператора new. В этом случае все они будут автоматически проинициализированы нулевыми значениями. Массив из трех целых чисел, содержащий величины 3, 7 и 11, можно задать так:
![int a[] = {3, 7, 11};](/sites/default/files/tex_cache/531ab57729c6d44da61c966e6820f677.png)
Элементы любого массива нумеруются с нуля,
а для доступа к
-му его элементу используется выражение
.
Язык Java отслеживает все попытки обратиться к несуществующему элементу
массива — при попытке работать, скажем с
, возникает
исключительная ситуация ( выход индекса за границу массива ),
так как последний элемент имеет индекс
, а не
.
В качестве более содержательного комментария к программе инвертирования
массива заметим, что выполнение цикла,
переставляющего элементы, завершается, как только будет достигнута середина
массива. Если условие продолжения цикла
заменить на
,
то процесс обмена не завершится после того, как массив уже будет инвертирован,
и обмен элементов продолжится, что приведет к двукратному инвертированию
массива, что эквивалентно тождественному преобразованию.
Рассмотрим еще одну задачу.
Задача 5.7. Напишите программу, печатающую максимальный элемент непустого массива.
Текст программы
public class MaxArr {
public static void main(String[] args) throws Exception {
int n, i, a[];
n = Xterm.inputInt("Введите длину массива n -> ");
a = new int[n];
for (i=0; i<n; i++)
a[i] = Xterm.inputInt("Введите a[" + i + "] -> ");
int max = a[0];
for (i=1; i<n; i++)
if (a[i] > max)
max = a[i];
Xterm.println("Максимальный элемент массива = " + max);
}
}В заключение рассмотрим задачу, включающую дополнительное требование на структуру программы.
Задача 5.8. Напишите программу, печатающую количество максимальных элементов непустого массива, в которой используется только один цикл.
Текст программы
public class NumMaxArr {
public static void main(String[] args) throws Exception {
int n, i, a[];
n = Xterm.inputInt("Введите длину массива n -> ");
a = new int[n];
int max = Integer.MIN_VALUE;
int nMax = 0;
for (i=0; i<n; i++) {
a[i] = Xterm.inputInt("Введите a[" + i + "] -> ");
if (a[i] > max) {
max = a[i];
nMax = 1;
} else if (a[i] == max)
nMax += 1;
}
Xterm.println("Количество макс. элементов = " + nMax);
}
}Использование константы Integer.MIN_VALUE позволяет избежать необходимости присваивания переменной max значения нулевого элемента массива до начала циклического просмотра остальных элементов.
Можно заметить, что при решении этой задачи массив по существу не используется. Если в этой программе удалить описание массива a, заменив его на описание целой переменной a, и произвести замену всех вхождений выражения a[i] на a, то программа останется работающей.
Задача сортировки является классической задачей на массивы.
Задача 5.9. Напишите программу, которая вводит с клавиатуры непустой массив целых чисел, печатает его, затем сортирует (то есть переставляет его элементы так, чтобы они располагались в неубывающем порядке), и вновь печатает.
Приведенный ниже алгоритм, который последовательно обменивает все соседние
пары элементов, расположенных в неправильном порядке, является одним
из самых медленных алгоритмов сортировки
среди всех широко известных — его асимптотическая сложность является
квадратичной (
).
Текст программы
public class Sort {
private static void sort(int[] a, int n) {
int i, j, t;
for (i=0; i<n-1; i+=1)
for (j=n-1; j>i; j-=1)
if (a[j] < a[j-1]) {
t=a[j]; a[j]=a[j-1]; a[j-1]=t;
}
}
public static void main(String[] args) throws Exception {
int n, i, a[];
n = Xterm.inputInt("Введите длину массива n -> ");
a = new int[n];
for (i=0; i<n; i++)
a[i] = Xterm.inputInt("Введите a[" + i + "] -> ");
Xterm.print("Исходный массив\n");
for (i=0; i<n; i++)
Xterm.print(" " + a[i]);
Xterm.print("\n");
sort(a, n);
Xterm.print("Отсортированный массив\n");
for (i=0; i<n; i++)
Xterm.print(" " + a[i]);
Xterm.print("\n");
}
}