說明
選擇排序(Selection sort)、插入排序(Insertion sort)與氣泡排序(Bubble sort)這三個排序方式是初學排序所必須知道的三個基本排序方式,它們由於速度不快而不實用(平均與最快的時間複雜度都是O(n2)),然而它們排序的方式確是值得觀察與探討的。
解法
將要排序的對象分作兩部份,一個是已排序的,一個是未排序的,從後端未排序部份選擇一個最小值,並放入前端已排序部份的最後一個,例如:
排序前:70 80 31 37 10 1 48 60 33 80
- [1] 80 31 37 10 70 48 60 33 80 選出最小值1
- [1 10] 31 37 80 70 48 60 33 80 選出最小值10
- [1 10 31] 37 80 70 48 60 33 80 選出最小值31
- [1 10 31 33] 80 70 48 60 37 80 ......
- [1 10 31 33 37] 70 48 60 80 80 ......
- [1 10 31 33 37 48] 70 60 80 80 ......
- [1 10 31 33 37 48 60] 70 80 80 ......
- [1 10 31 33 37 48 60 70] 80 80 ......
- [1 10 31 33 37 48 60 70 80] 80 ......
像是玩樸克一樣,我們將牌分作兩堆,每次從後面一堆的牌抽出最前端的牌,然後插入前面一堆牌的適當位置,例如:
排序前:92 77 67 8 6 84 55 85 43 67
- [77 92] 67 8 6 84 55 85 43 67 將77插入92前
- [67 77 92] 8 6 84 55 85 43 67 將67插入77前
- [8 67 77 92] 6 84 55 85 43 67 將8插入67前
- [6 8 67 77 92] 84 55 85 43 67 將6插入8前
- [6 8 67 77 84 92] 55 85 43 67 將84插入92前
- [6 8 55 67 77 84 92] 85 43 67 將55插入67前
- [6 8 55 67 77 84 85 92] 43 67 ......
- [6 8 43 55 67 77 84 85 92] 67 ......
- [6 8 43 55 67 67 77 84 85 92] ......
顧名思義,就是排序時,最大的元素會如同氣泡一樣移至右端,其利用比較相鄰元素的方法,將大的元素交換至右端,所以大的元素會不斷的往右移動,直到適當的位置為止。
基本的氣泡排序法可以利用旗標的方式稍微減少一些比較的時間,當尋訪完陣列後都沒有發生任何的交換動作,表示排序已經完成,而無需再進行之後的迴圈比較與交換動作,例如:
排序前:95 27 90 49 80 58 6 9 18 50
- 27 90 49 80 58 6 9 18 50 [95] 95浮出
- 27 49 80 58 6 9 18 50 [90 95] 90浮出
- 27 49 58 6 9 18 50 [80 90 95] 80浮出
- 27 49 6 9 18 50 [58 80 90 95] ......
- 27 6 9 18 49 [50 58 80 90 95] ......
- 6 9 18 27 [49 50 58 80 90 95] ......
- 6 9 18 [27 49 50 58 80 90 95] 由於接下來不會再發生交換動作,排序提早結束
在上面的例子當中,還加入了一個觀念,就是當進行至i與i+1時沒有交換的動作,表示接下來的i+2至n已經排序完畢,這也增進了氣泡排序的效率。
#include <stdio.h> #include <stdlib.h> #include <time.h> #define MAX 10 #define SWAP(x,y) {int t; t = x; x = y; y = t;}
void selectionSort(int[]); // 選擇排序 void insertionSort(int[]); // 插入排序 void bubbleSort(int[]); // 氣泡排序
int main(void) { srand(time(NULL));
printf("排序前:"); int number[MAX] = {0}; int i; for(i = 0; i < MAX; i++) { number[i] = rand() % 100; printf("%d ", number[i]); }
printf("\n請選擇排序方式:\n"); printf("(1)選擇排序\n(2)插入排序\n(3)氣泡排序\n:"); scanf("%d", &i);
switch(i) { case 1: selectionSort(number); break; case 2: insertionSort(number); break; case 3: bubbleSort(number); break; default: printf("選項錯誤(1..3)\n"); }
int k; for(k = 0; k < MAX; k++) printf("%d ", number[k]); printf("\n"); return 0; }
void selectionSort(int number[]) { int i; for(i = 0; i < MAX-1; i++) { int m = i; int j; for(j = i+1; j < MAX; j++) if(number[j] < number[m]) m = j;
if(i != m) SWAP(number[i], number[m]) } }
void insertionSort(int number[]) { int j; for(j = 1; j < MAX; j++) { int tmp = number[j]; int i = j - 1; while(tmp < number[i]) { number[i+1] = number[i]; i--; if(i == -1) break; } number[i+1] = tmp; } }
void bubbleSort(int number[]) { int flag = 1; int i; for(i = 0; i < MAX-1 && flag == 1; i++) { flag = 0; int j; for(j = 0; j < MAX-i-1; j++) { if(number[j+1] < number[j]) { SWAP(number[j+1], number[j]); flag = 1; } } } }
public class Sort { public static void selection(int[] number) { for(int i = 0; i < number.length - 1; i++) { int m = i; for(int j = i + 1; j < number.length; j++) if(number[j] < number[m]) m = j;
if(i != m) swap(number, i, m); } } public static void insertion(int[] number) { for(int j = 1; j < number.length; j++) { int tmp = number[j]; int i = j - 1; while(i != -1 && tmp < number[i]) { number[i+1] = number[i]; i--; } number[i+1] = tmp; } } public static void bubble(int[] number) { boolean flag = true; for(int i = 0; i < number.length-1 && flag; i++) { flag = false; for(int j = 0; j < number.length-i-1; j++) { if(number[j+1] < number[j]) { swap(number, j+1, j); flag = true; } } } } private static void swap(int[] number, int i, int j) { int t = number[i]; number[i] = number[j]; number[j] = t; } }
from functools import reduce class Sort: def selection(xs): return [] if not xs else Sort.__select(xs) def __select(xs): min = reduce(lambda m, k: k if m> k else m, xs) remain = [elem for elem in xs if elem != min] return xs if not remain \ else [elem for elem in xs if elem == min] + Sort.__select(remain) def insertion(xs): return [] if not xs \ else Sort.__insert(xs[0], Sort.insertion(xs[1:])) def __insert(x, xs): return [x] + xs if not xs or x <= xs[0] \ else [xs[0]] + Sort.__insert(x, xs[1:]) def bubble(xs): return [] if not xs else Sort.__up(xs) def __up(xs): if not xs[1:]: return xs else: s = Sort.bubble(xs[1:]) return [s[0]] + Sort.__up([xs[0]] + s[1:]) if xs[0] > s[0] \ else [xs[0]] + s
object Sort { def selection(xs: List[Int]): List[Int] = { if(xs.isEmpty) Nil else select(xs) } private def select(xs: List[Int]): List[Int] = { val min = xs.reduceLeft((m, k) => if(m > k) k else m) val remain = xs.filter(_ != min) if(remain.isEmpty) xs else xs.filter(_ == min) ++ select(remain) } def insertion(xs: List[Int]): List[Int] = { if(xs.isEmpty) Nil else insert(xs.head, insertion(xs.tail)) } private def insert(x: Int, xs: List[Int]): List[Int] = { if(xs.isEmpty || x <= xs.head) x :: xs else xs.head :: insert(x, xs.tail) } def bubble(xs: List[Int]):List[Int] = { if(xs.isEmpty) Nil else up(xs) } private def up(xs: List[Int]): List[Int] = { if(xs.tail.isEmpty) xs else { val s = bubble(xs.tail) if(xs.head > s.head) s.head :: up(xs.head :: s.tail) else xs.head :: s } } }
class Array def comprehend(&block) return self if block.nil? self.collect(&block).compact end end
class Sort def self.selection(xs) xs.empty? ? [] : select(xs) end def self.select(xs) min = xs.reduce { |m, k| m > k ? k : m } remain = xs.comprehend { |elem| elem if elem != min} remain.empty? ? xs : xs.comprehend { |elem| elem if elem == min} + select(remain) end private_class_method :select def self.insertion(xs) xs.empty? ? [] : insert(xs[0], insertion(xs[1..-1])) end def self.insert(x, xs) xs.empty? || x <= xs[0] ? [x] + xs : [xs[0]] + insert(x, xs[1..-1]) end private_class_method :insert def self.bubble(xs) xs.empty? ? [] : up(xs) end def self.up(xs) if xs[1..-1].empty? xs else s = bubble(xs[1..-1]) xs[0] > s[0] ? [s[0]] + up([xs[0]] + s[1..-1]) : [xs[0]] + s end end private_class_method :up end
|