淺談排序算法之選擇排序(2)

筆者在上一篇博客中回顧了下冒泡排序(Bubble-Sort),這裏寫篇博客講講選擇排序(Selection-Sort)。選擇排序在每一次的迭代中,不直接交換相鄰元素,而是從數組中選擇出當前數組中的最小值(最大值)的索引,並於當前待排序位置的索引進行比較。若不相等,則交換之,亦即會出現如下情況

當前最小值:  3 -> [7, 36, 18, 7, 39, 35, 12, 29, 37, 3, 16, 38, 11, 26, 27, 33, 12, 7, 39, 25]
當前最小值:  7 -> [3, 36, 18, 7, 39, 35, 12, 29, 37, 7, 16, 38, 11, 26, 27, 33, 12, 7, 39, 25]

而冒泡排序則是在每一次迭代中,對不滿足條件的相鄰元素進行交換從而確保每次迭代都會將最小值或者最大值“冒泡”到數組前面或者後面。算法本身不難,在給出相應代碼實現之前,先簡單分析下其時間複雜度。設數組長度爲n,其時間複雜度可以表示爲O(n^2),且一般情況下,選擇排序算法都是穩定的,除非將判斷條件之一

array[index] > array[i]

修改爲

array[index] >= array[i]

完整代碼如下

import com.sun.istack.internal.NotNull;

import java.util.Arrays;
import java.util.Random;

/**
 * A demo of {@code SelectionSort}.
 *
 * @author Mr.K
 */
public class SelectionSort {

    public static void main(String[] args) {
        int N = 20;
        int[] numbers = new int[N];
        Random random = new Random();
        for (int i = 0; i < N; i++) {
            numbers[i] = random.nextInt(2 * N);
        }
        System.out.println(Arrays.toString(numbers) + "\n");
        selectionSort(numbers);
        System.out.println("\n" + Arrays.toString(numbers));
    }

    /**
     * Accepts an array and sorts the specified array by algorithm {@code SelectionSort}.
     * This is one version of {@code SelectionSort} where the minimum number will be
     * selected from the remaining array in each iteration and that number will be moved
     * to the head of the array, in ascending order.
     * <ul>
     *     <li>This algorithm starts from index 0 and to the last index of the specified
     *     array.</li>
     *     <li>In each iteration, the first step is to find the minimum number from i
     *     (inclusive), which is the number of iteration, to the last index(exclusive)
     *     of the array.</li>
     *     <li>If current cursor index does not equal to the index of the minimum number
     *     of the remaining array, then exchange these two number by <em>Xor</em>.</li>
     *     <li>Cause the condition to find the minimum number of the remaining array is
     *     <blockquote>
     *         index = array[index] > array[i] ? i : index;
     *     </blockquote>
     *     which means only when a certain number is less than current number, exchange
     *     will be implemented. So {@code SelectionSort} is stable. If exchanges happen
     *     when there are two number with the same value, {@code SelectionSort} becomes
     *     unstable.</li>
     * </ul>
     * From the process, there's no doubt that the cost of time of {@code SelectionSort}
     * equals O(n^2) for there are two <em>For-Loops</em>, which may become a bottleneck
     * in the bad cases.
     *
     * @param numbers specified array to be sorted
     */
    public static void selectionSort(@NotNull int[] numbers) {
        for (int i = 0; i < numbers.length; i++) {
            int indexOfMinNumber = findMinNumberIndex(numbers, i, numbers.length);
            System.out.println("第" + String.format("%2d", i) + "步, 當前最小值: " +
                    String.format("%2d", numbers[indexOfMinNumber]) + " -> " + Arrays.toString(numbers));
            if (i != indexOfMinNumber) {
                int temp = numbers[i] ^ numbers[indexOfMinNumber];
                numbers[i] = temp ^ numbers[i];
                numbers[indexOfMinNumber] = temp ^ numbers[indexOfMinNumber];
            }
        }
    }

    /**
     * Accepts an array, finds the index of the minimum number of the specified array in
     * the range from start index(inclusive) to end index(exclusive) and returns the index.
     * Be aware that only when a certain number is less than current number, exchange will
     * happen to ensure that {@code SelectionSort} is stable.
     *
     * @param array specified array to find index of the minimum number
     * @param start index of start position(inclusive)
     * @param end   index of end position(exclusive)
     * @return index of the minimum number in the specified array
     */
    public static int findMinNumberIndex(@NotNull int[] array, @NotNull int start, @NotNull int end) {
        int index = start;
        for (int i = start; i < end; i++) {
            index = array[index] > array[i] ? i : index;
        }
        return index;
    }
    
}

某次運行結果如下

[18, 12, 23, 33, 23, 6, 39, 31, 20, 4, 22, 22, 13, 27, 7, 9, 34, 29, 29, 34]0, 當前最小值:  4 -> [18, 12, 23, 33, 23, 6, 39, 31, 20, 4, 22, 22, 13, 27, 7, 9, 34, 29, 29, 34]1, 當前最小值:  6 -> [4, 12, 23, 33, 23, 6, 39, 31, 20, 18, 22, 22, 13, 27, 7, 9, 34, 29, 29, 34]2, 當前最小值:  7 -> [4, 6, 23, 33, 23, 12, 39, 31, 20, 18, 22, 22, 13, 27, 7, 9, 34, 29, 29, 34]3, 當前最小值:  9 -> [4, 6, 7, 33, 23, 12, 39, 31, 20, 18, 22, 22, 13, 27, 23, 9, 34, 29, 29, 34]4, 當前最小值: 12 -> [4, 6, 7, 9, 23, 12, 39, 31, 20, 18, 22, 22, 13, 27, 23, 33, 34, 29, 29, 34]5, 當前最小值: 13 -> [4, 6, 7, 9, 12, 23, 39, 31, 20, 18, 22, 22, 13, 27, 23, 33, 34, 29, 29, 34]6, 當前最小值: 18 -> [4, 6, 7, 9, 12, 13, 39, 31, 20, 18, 22, 22, 23, 27, 23, 33, 34, 29, 29, 34]7, 當前最小值: 20 -> [4, 6, 7, 9, 12, 13, 18, 31, 20, 39, 22, 22, 23, 27, 23, 33, 34, 29, 29, 34]8, 當前最小值: 22 -> [4, 6, 7, 9, 12, 13, 18, 20, 31, 39, 22, 22, 23, 27, 23, 33, 34, 29, 29, 34]9, 當前最小值: 22 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 39, 31, 22, 23, 27, 23, 33, 34, 29, 29, 34]10, 當前最小值: 23 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 31, 39, 23, 27, 23, 33, 34, 29, 29, 34]11, 當前最小值: 23 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 39, 31, 27, 23, 33, 34, 29, 29, 34]12, 當前最小值: 27 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 31, 27, 39, 33, 34, 29, 29, 34]13, 當前最小值: 29 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 31, 39, 33, 34, 29, 29, 34]14, 當前最小值: 29 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 29, 39, 33, 34, 31, 29, 34]15, 當前最小值: 31 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 29, 29, 33, 34, 31, 39, 34]16, 當前最小值: 33 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 29, 29, 31, 34, 33, 39, 34]17, 當前最小值: 34 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 29, 29, 31, 33, 34, 39, 34]18, 當前最小值: 34 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 29, 29, 31, 33, 34, 39, 34]19, 當前最小值: 39 -> [4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 29, 29, 31, 33, 34, 34, 39]

[4, 6, 7, 9, 12, 13, 18, 20, 22, 22, 23, 23, 27, 29, 29, 31, 33, 34, 34, 39]

上一篇-淺談排序算法之冒泡排序

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章