1. Введение
В этом учебнике мы объясним, как работает алгоритм сортировки на месте.
2. Алгоритмы на месте
Алгоритмы на месте — это алгоритмы, которые не нуждаются в вспомогательной структуре данных для преобразования входных данных. В принципе, это означает, что алгоритм не использует дополнительное пространство для ввода манипуляции. Он практически переопределяет вход с выходом.
Однако на самом деле алгоритм может потребовать небольшого и неконтуятного дополнительного пространства для вспомогательных переменных. Сложность этого пространства в большинстве случаев O (журнал n) , хотя иногда разрешается что-либо меньшее, чем линейное.
3. Псевдокод
Давайте теперь посмотрим какой-нибудь псевдокод и сравним алгоритм на месте с неместо него.
Мы предположим, что мы хотим обратить вспять массив n Числа.
3.1. Алгоритм на месте
Если мы подумаем о проблеме, мы увидим, что у нас есть входной массив и обратный массив в качестве вывода. В конце концов, нам на самом деле не нужен наш оригинальный массив, только обратный.
Тогда почему бы нам не переписать вход вместо того, чтобы перейти его значения к совершенно новому массиву, так как это может выглядеть как наиболее очевидный метод? Чтобы сделать это, Нам понадобится только одна дополнительная переменная временно хранить значения, с которые мы в настоящее время работаем:
reversInPlace(array A[n]) for i from 0 to n/2 temp = A[i] A[i] = A[n - 1 - i] A[n - 1 - i] = temp
Примечательно отметить, что независимо от того, насколько велик массив, дополнительное пространство, которое нам нужно, всегда будет O(1) в этом случае.
Иллюстрация показывает, что нам нужно меньше шагов, чем в предыдущем случае:
3.2. Алгоритм вне места
С другой стороны, мы также можем сделать это в довольно простой, более очевидным образом. Мы можем создать новый массив того же размера, скопировать значения из исходного в соответствующем порядке, а затем удалить исходный массив:
reverseOutOfPlace(array A[n]) create new array B[n] for i from 0 to n - 1 B[i] = A[i] delete A return B
Хотя это будет делать то, что мы хотели, это не достаточно эффективно. У нас О(н) дополнительное пространство, необходимое так как у нас есть два массива, чтобы манипулировать . Кроме того, создание и удаление нового массива обычно является медленной операцией.
Давайте посмотрим на иллюстрацию процесса:
4. Реализация Java
Давайте теперь посмотрим, как мы можем реализовать в Java то, что мы узнали в предыдущем разделе.
Во-первых, мы реализуем алгоритм на месте:
public static int[] reverseInPlace(int A[]) { int n = A.length; for (int i = 0; i < n / 2; i++) { int temp = A[i]; A[i] = A[n - 1 - i]; A[n - 1 - i] = temp; } return A; }
Мы можем легко проверить, что это работает, как ожидалось:
@Test public void givenArray_whenInPlaceSort_thenReversed() { int[] input = {1, 2, 3, 4, 5, 6, 7}; int[] expected = {7, 6, 5, 4, 3, 2, 1}; assertArrayEquals("the two arrays are not equal", expected, InOutSort.reverseInPlace(input)); }
Во-вторых, давайте проверим вне места реализации алгоритма:
public static int[] reverseOutOfPlace(int A[]) { int n = A.length; int[] B = new int[n]; for (int i = 0; i < n; i++) { B[n - i - 1] = A[i]; } return B; }
Тест довольно прост:
@Test public void givenArray_whenOutOfPlaceSort_thenReversed() { int[] input = {1, 2, 3, 4, 5, 6, 7}; int[] expected = {7, 6, 5, 4, 3, 2, 1}; assertArrayEquals("the two arrays are not equal", expected, InOutSort.reverseOutOfPlace(input)); }
5. Примеры
Есть много алгоритмов сортировки, которые используют на месте подход. Некоторые из них являются сортировка вставки , пузырь рода , куча рода , quicksort , и оболочки рода, и вы можете узнать больше о них и проверить свои реализации Java.
Кроме того, мы должны упомянуть гребень рода и heapsort. Все они имеют космическую сложность O (журнал n) .
Было бы также полезно узнать больше о теории Big-O Notation , а также проверить некоторые практические примеры Java о сложности алгоритма .
6. Заключение
В этой статье мы описали так называемые на месте алгоритмы, проиллюстрировали, как они работают с использованием псевдокода и несколько примеров, перечислили несколько алгоритмов, которые работают по этому принципу, и, наконец, реализовали основные примеры в Java.
Как обычно, весь код можно найти более на GitHub .