排序算法系列——直接選擇排序

前面兩篇介紹了兩種插入排序算法:直接插入排序和希爾排序。這篇介紹選擇排序的一種:直接選擇排序。從名字就可以看出直接選擇排序與直接插入排序很相似,兩者相同點在與都是將待排序序列分成有序區和無序區兩部分,不同之處在於直接插入排序是從無序區選出一個插入到有序區合適的位置,而直接選擇排序是從無序區選出最小的一個插入到有序區尾部,使得有序區保持有序。
基本思想
一組待排序的數據,首先將其劃分成兩部分,一部分是已排好序的,另一部分是待排序的,然後依次從待排序部分取出最小的元素插入到已排序部分的尾部,保證有序始終是已排好序的,等待排序部分全部取出放入已排序部分之後整個排序過程就完成了。 此處與直接插入排序不同之處在於,在從無序部分選擇一個元素插入到有序部分時,是挑選無序部分中最小的元素,所以在挑選時需要同無序部分的每個元素進行對比,找到最小的元素。
實現要點
將待排序序列看做爲無序部分(有序部分長度爲0)。然後從待排序部分使用遍歷比較得到最小值的位置,將其與無序部分的第一個元素進行交換(第一輪與data[0]進行交換),重複該過程直到無序部分只剩下一個元素,即完成了排序。
Java實現

package com.vicky.sort;

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

/**
 * <p>
 * 選擇排序:直接選擇排序
 * 
 * 基本思想:
 * 直接選擇排序同直接插入排序,也是將整個序列分爲有序區和無序區,所不同的是直接播放排序是將無序區的第一個元素直接插入到有序區以形成一個更大的有序區
 * ,而直接選擇排序是從無序區選一個最小的元素直接放到有序區的最後。
 * 
 * 時間複雜度:O(n^2)
 * 
 * 空間複雜度:θ(1)
 * 
 * 穩定性:不穩定
 * </p>
 * 
 * @author Vicky
 * @date 2015-8-13
 */
public class StraightSelectionSort {
    /**
     * 排序
     * 
     * @param data
     *            待排序的數組
     */
    public static <T extends Comparable<T>> void sort(T[] data) {
        long start = System.nanoTime();
        if (null == data) {
            throw new NullPointerException("data");
        }
        if (data.length == 1) {
            return;
        }
        for (int st = 0; st < data.length - 1; st++) {
            int j = st + 1;
            int min = st;
            // 找到最小元素的位置
            for (; j < data.length; j++) {
                if (data[j].compareTo(data[min]) < 0) {
                    min = j;
                }
            }
            // 將最小元素放到有序區尾部
            if (min != st) {// 避免跟自身交換
                T temp = data[st];
                data[st] = data[min];
                data[min] = temp;
            }
        }
        System.out.println("use time:" + (System.nanoTime() - start) / 1000000);
    }

    public static void main(String[] args) {
        Random ran = new Random();
        Integer[] data = new Integer[100000];
        for (int i = 0; i < data.length; i++) {
            data[i] = ran.nextInt(10000000);
        }
        StraightSelectionSort.sort(data);
        System.out.println(Arrays.toString(data));
    }
}

效率分析
(1)時間複雜度
O(n^2)
選擇排序的交換操作介於0和(n-1)次之間。選擇排序的比較操作爲n(n-1)/2次之間。選擇排序的賦值操作介於0和3(n-1)次之間。比較次數O(n^2),比較次數與關鍵字的初始狀態無關,總的比較次數N=(n-1)+(n-2)+…+1=n\times(n-1)/2。交換次數O(n),最好情況是,已經有序,交換0次;最壞情況是,逆序,交換n-1次。所以直接選擇排序的時間複雜度是O(n^2)。
(2)空間複雜度
O(1)
-從空間來看,它只需要一個元素的輔助空間,用於元素的位置交換O(1)。
(3)穩定性
不穩定。
-我們假設一個序列{1,3,5,10A,10B,7},看這個數列,假設前面三個是有序區,後面三個是無序區,則無序區中最小的元素是7,和無序區的首元素交換10A交換,則可以看到序列變成了{1,3,5,7,10B,10A},然後繼續,無序區就剩下{10B,10A},我們又可以看到,這裏又是一個等號問題,同樣,前面的交換是必然的,而後面的交換(如果等於也要交換)則不是必然的,爲了減少元素交換,直接選擇排序是不穩定的。
參考文章
選擇排序-維基百科
排序算法的穩定性

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