Книга: Основы программирования с Java
Назад: Примеры
Дальше: Сортировка

Перестановка элементов

Одна операция, которая часто встречается при работе с массивами, это перестановка двух элементов.





В этом примере значения второго и третьего элементов массива scoreArray будут переставлены.

Это похоже на то, как вы обмениваетесь подарками на Рождество.

Давайте сделаем нашу первую попытку написать метод перестановки двух элементов в массиве А.

Я назову этот метод badSwap, так что вы поймете, что этот метод не предназначен для работы.







Метод badSwap имеет два параметра типа double.

При вызове этого метода мы хотим переставить элементы с индексами 1 и 2 в массиве А, и они будут переданы в метод как параметры.

Эти параметры будут обрабатываться как локальные переменные, и память будет выделяться для них из стека памяти.

Так как отдельные элементы массива A[1] и A[2] имеют тип double, который является примитивным типом, их значения будут скопированы в область памяти для параметров.

Теперь n1 имеет значение 90, и n2 имеет значение 80.

Когда в badSwap выполняется первое выражение n1 равно n2, значение n2, которое равно 80, присваивается n1, и старое значение n1 стирается и заменяется на 80.

Теперь и n1 и n2 имеют одинаковое значение 80.

Когда выполняется второе выражение n2 равно n1, значение n1, которое равно 80, будет присвоено n2.

В результате обе переменные n1 и n2 получат значение 80 в конце выполнения метода.

Ясно, что это не то, для чего этот метод предназначен.

Один способ решить эту проблему, это в начале где-нибудь сохранить значение n1, перед выполнением первого выражения n1 равно n2, так что старое значение n1 может позже быть присвоено n2.

Давайте посмотрим на другую версию метода перестановки с именем swap2.







Локальная переменная temp объявлена в методе swap2.

Поэтому в дополнение к переменным параметров n1 и n2, еще одна дополнительная ячейка памяти должна быть выделена для переменной temp.

Когда выполняется первое выражение temp равно n1, значение n1 или 90 присваивается temp.

Так что сохраняется временная копия n1.

Когда выполняется второе выражение n1 равно n2, значение n1 удаляется и заменяется на 80.

Заметьте, что теперь обе переменные n1 и n2 имеют одинаковое значение 80.

Вместо того, чтобы присвоить n1 в n2, как мы делали перед этим в методе badSwap, присваивать мы теперь будем temp, которая хранит старое значение n1, в n2.

Так что в конце выполнения метода значения n1 и n2 будут переставлены.

Но решили ли мы действительно проблему перестановки значений элементов массива A[1] и A[2]?

Элементы A[1] и A[2] все еще имеют те же значения, как и раньше.

Помним, что после выполнения метода swap2, вся информация, содержащаяся в локальных переменных, будет удалена и никакой перестановки не будет сделано в элементах массива.

Это потому что отдельные элементы массива A[1] и A[2] имеют тип double, который является примитивным типом.

Поэтому только копии значений передаются в метод swap2, и все что изменяется в методе swap2, не влияет на значения массива.

Так как мы можем решить эту проблему?

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

Это легко сделать, и вы можете подумать, как это можно реализовать.

Давайте напишем более общий метод для перестановки двух элементов в массиве, даже если массив и метод определены не в одном и том же классе.







Метод swap здесь имеет три параметра.

Первый параметр – это массив типа double.

Далее index1 и index2, это индексы элементов массива для перестановки.

Заметьте, что тело этого метода похоже на предыдущий метод.

Для иллюстрации, как метод работает: массив A и индексы 1 и 2 передаются в метод.

Далее метод переставляет второй элемент или 1 индекс и третий элемент или 2 индекс массива А.

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

Массив А используется как первый аргумент.

Так как А – это переменная ссылочного типа, помним, что мы используем аналогию больших посылок для объектов, которые не помещаются в слот памяти.

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

Так что здесь переменная параметра arr дает адрес начала области памяти для массива А.

Параметры index1 и index2 дают значения 1 и 2, как аргументы вызова метода.

Объявление локальной переменной temp выделит память типа double.

Далее будет вычисляться правая сторона этих выражений.

При этом будет сделана ссылка на элемент массива arr, имеющий индекс index1, и это 1.

Для массива arr, его ссылочная переменная указывает на начало массива А.

Эта переменная знает, как обнаружить массив А, а затем извлечь элемент с индексом 1 или второй элемент массива.

Так как второй элемент А имеет значение 90, это значение будет присвоено переменной temp.

Когда будет вычисляться правая часть второго выражения, значение элемента А с индексом index2, равным 2, будет извлечено.

Это даст значение 80, которое будет присвоено элементу массива с индексом index1, равным 1.

Заметьте, что значение второго элемента А теперь изменилось с 80 на 90.

Последнее выражение метода присвоит значение переменной temp элементу массива А с индексом index2, и так как temp имеет значение 90, начальное значение третьего элемента массива А заменится на 90.

Теперь в конце выполнения метода, второй и третий элементы массива А обменяются значениями.

Назад: Примеры
Дальше: Сортировка