1. 基本原理
將待排序的元素分為已排序(初始為空)和未排序兩組,依次將未排序的元素中值最小的元素放入已排序的組中。
?
直接選擇排序簡單直觀,但性能略差;堆排序是一種較高效的選擇排序方法,但實現起來略微復雜。
?
2. 直接選擇排序
基本過程為:
- 在一組元素R[i]到R[n]中選擇具有最小關鍵碼的元素
- 若它不是這組元素中的第一個元素,則將它與這組元素中的第一個元素對調。
- 除去具有最小關鍵字的元素,在剩下的元素中重復第(1)、(2)步,直到剩余元素只有一個為止。
?
?
3. 代碼實現


1 package com.windy.sort; 2 3 import java.util.Arrays; 4 5 import org.junit.Test; 6 7 public class SelectSort { 8 9 class DataWrap implements Comparable<DataWrap> { 10 int data; 11 String flag; 12 13 public DataWrap(int data, String flag) { 14 this.data = data; 15 this.flag = flag; 16 } 17 18 @Override 19 public String toString() { 20 return data + flag; 21 } 22 23 @Override 24 public int compareTo(DataWrap dw) { 25 26 return this.data > dw.data ? 1 : (this.data == dw.data ? 0 : -1); 27 28 } 29 } 30 31 @Test 32 public void test1() { 33 34 DataWrap[] dw = new DataWrap[] { 35 new DataWrap(-9, ""), 36 new DataWrap(1, ""), 37 new DataWrap(-47, "*"), 38 new DataWrap(1246, ""), 39 new DataWrap(758, ""), 40 new DataWrap(-123, ""), 41 new DataWrap(5, ""), 42 new DataWrap(638, ""), 43 new DataWrap(-47, ""), 44 new DataWrap(5, "*") 45 }; 46 47 System.out.println("排序前:\n" + Arrays.toString(dw)); 48 selectSort(dw); 49 System.out.println("排序后:\n" + Arrays.toString(dw)); 50 } 51 52 @Test 53 public void test2() { 54 DataWrap[] dw = new DataWrap[] { 55 new DataWrap(-9, ""), 56 new DataWrap(1, ""), 57 new DataWrap(-47, "*"), 58 new DataWrap(1246, ""), 59 new DataWrap(758, ""), 60 new DataWrap(-123, ""), 61 new DataWrap(5, ""), 62 new DataWrap(638, ""), 63 new DataWrap(-47, ""), 64 new DataWrap(5, "*") 65 }; 66 67 System.out.println("排序前:\n" + Arrays.toString(dw)); 68 selectSort2(dw); 69 System.out.println("排序后:\n" + Arrays.toString(dw)); 70 } 71 72 // 直接選擇排序 73 private static void selectSort(DataWrap[] dw) { 74 75 int length = dw.length; 76 77 System.out.println("排序中..."); 78 79 for (int i = 0; i < length - 1; i++) { 80 81 for (int j = i + 1; j < length; j++) { 82 if (dw[i].compareTo(dw[j]) > 0) { 83 DataWrap temp; 84 temp = dw[i]; 85 dw[i] = dw[j]; 86 dw[j] = temp; 87 } 88 } 89 90 System.out.println(Arrays.toString(dw)); 91 } 92 93 } 94 95 /* 96 * 直接選擇排序改進版 用臨時變量記錄最小值的下標,而不是選擇馬上交換 在對比一輪結束之后,才選擇交換 97 */ 98 private static void selectSort2(DataWrap[] dw) { 99 int length = dw.length; 100 101 System.out.println("排序中..."); 102 for (int i = 0; i < length - 1; i++) { 103 int min = i; 104 105 for (int j = i + 1; j < length; j++) { 106 // 用最小值去對比,而不是dw[i] 107 if (dw[min].compareTo(dw[j]) > 0) { 108 min = j; 109 } 110 } 111 112 DataWrap temp; 113 temp = dw[i]; 114 dw[i] = dw[min]; 115 dw[min] = temp; 116 117 System.out.println(Arrays.toString(dw)); 118 } 119 120 } 121 122 }
?
結果打印:
排序前:
[-9, 1, -47*, 1246, 758, -123, 5, 638, -47, 5*]
排序中...
[-123, 1, -9, 1246, 758, -47*, 5, 638, -47, 5*]
[-123, -47*, 1, 1246, 758, -9, 5, 638, -47, 5*]
[-123, -47*, -47, 1246, 758, 1, 5, 638, -9, 5*]
[-123, -47*, -47, -9, 1246, 758, 5, 638, 1, 5*]
[-123, -47*, -47, -9, 1, 1246, 758, 638, 5, 5*]
[-123, -47*, -47, -9, 1, 5, 1246, 758, 638, 5*]
[-123, -47*, -47, -9, 1, 5, 5*, 1246, 758, 638]
[-123, -47*, -47, -9, 1, 5, 5*, 638, 1246, 758]
[-123, -47*, -47, -9, 1, 5, 5*, 638, 758, 1246]
排序后:
[-123, -47*, -47, -9, 1, 5, 5*, 638, 758, 1246]
?
4. 算法效率分析
- 算法的時間效率:無論初始狀態如何,在第i趟排序中選擇最小關鍵碼的元素,需做n-i次比較,因此總的比較次數為:
? ? ? ??
?
- 算法的空間效率:空間效率很高,只需要一個附加程序單元用于交換,其空間效率為O(1)
?
- 算法的穩定性:不穩定