排序演算法:氣泡排序、插入排序、選擇排序、快速排序對比
阿新 • • 發佈:2019-02-02
package com.test; public class T { public static void main(String[] args) { long start = System.currentTimeMillis(); int[] arr1 = createArray(); int[] arr2 = createArray(); int[] arr3 = createArray(); int[] arr4 = createArray(); quick_sort qs = new quick_sort(); long end = System.currentTimeMillis(); System.out.println("Creating arrays uses time: " + (end - start)); start = System.currentTimeMillis(); bubble_sort(arr1); end = System.currentTimeMillis(); System.out.println("氣泡排序: " + (end - start)); start = System.currentTimeMillis(); insertion_sort(arr3); end = System.currentTimeMillis(); System.out.println("插入排序: " + (end - start)); start = System.currentTimeMillis(); selection_sort(arr2); end = System.currentTimeMillis(); System.out.println("選擇排序: " + (end - start)); start = System.currentTimeMillis(); qs.sort(arr4); end = System.currentTimeMillis(); System.out.println("快速排序: " + (end - start)); /* * Creating arrays uses time: 16 氣泡排序: 4651 插入排序: 1465 選擇排序: 1399 快速排序: * 14 */ } public static int[] createArray() { int length = 60000; int[] arr = new int[length]; int i = 0; for (; i < length; i++) { arr[i] = (int) (Math.random() * length); } return arr; } /** * 氣泡排序: * * 一、 重複的遍歷要排序的序列 n 次。(n為陣列的長度) 二、 對於每次遍歷: 2.1 要遍歷的元素個數減 1 (因為尾部的已經排好) 2.2 * 每次都要比較兩個元素。如果符合條件,則交換位置。 */ public static void bubble_sort(int[] arr) { int i, j, temp, len = arr.length; // 1. 遍歷 i 次 for (i = 0; i < len - 1; i++) // 2. 對於 0 到 len-i 中的元素 for (j = 0; j < len - 1 - i; j++) // 3. 如果前面的大,則交換(冒泡)到後面 if (arr[j] > arr[j + 1]) { temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } /** * 插入排序: * * 一、從陣列的第1個元素開始遍歷至第n個。(n為陣列的長度) 二、對於每一個遍歷到的元素: 2.1 向前倒著找(已經排好序的)自己的位置。 2.2 * 如果不符合條件,則前面的元素向後移動,與之互動位置。 直至條件符合。 */ public static void insertion_sort(int[] arr) { for (int i = 0; i < arr.length - 1; i++) { // 1. 遍歷每一個 i for (int j = i + 1; j > 0; j--) { // 2. 從 0-j 是已經排序好的。 if (arr[j - 1] <= arr[j]) break; // 位置已經找到,不用再比了。繼續下一個 i // 對於每一個 i,向後移動每一個j,騰出空間。直至找到 i 的位置。 int temp = arr[j]; arr[j] = arr[j - 1]; arr[j - 1] = temp; } } } /** * 選擇排序: * * 一、遍歷從 0 到 n 個位置。(n為陣列的長度) 二、對於每一個位置: 2.1 從剩餘的數中找到符合條件的,放到該位置上。 */ public static void selection_sort(int[] arr) { int i, j, min, temp, len = arr.length; // 1. 遍歷每一個 位置 i for (i = 0; i < len - 1; i++) { min = i; for (j = i + 1; j < len; j++) // 2. 遍歷每一個 j,找出最小的 if (arr[min] > arr[j]) min = j; // 3. 把 找出的值放在 i 的位置 temp = arr[min]; arr[min] = arr[i]; arr[i] = temp; } } } /** * 快速排序(Quicksort): 又稱為劃分交換排序(partition-exchange sort) * * 快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分為兩個子序列(sub-lists)。 步驟: 1. * 從序列中選一個數作為基準(pivot)。【本例中使用最後一個元素】 2. 分別從左右兩側開始向中間推進。 左側:從左至右前進,直至找到大於等於基準的數。 * 右側:從右至左前進,直至找到小於基準的數。 左右兩個數調換位置。 3. 重複2的過程,直至左右相碰,全部遍歷完一遍。 此時在相碰處: * 左側:所有的數都小於基準小。 右側:所有的數都大於或等於基準。 中間:基準元素的位置已確定了。 4. 把相碰處分為兩個子序列,遞迴的呼叫2,3步驟。 */ class quick_sort { int[] arr; private void swap(int x, int y) { int temp = arr[x]; arr[x] = arr[y]; arr[y] = temp; } private void quick_sort_recursive(int start, int end) { if (start >= end) return; int mid = arr[end]; int left = start, right = end - 1; // 1. left 區先和 right 區比 while (left < right) { while (arr[left] < mid && left < right) // 找到left中比mid大的或相等的。 left++; while (arr[right] >= mid && left < right) // 只找到right中比mid小的。 right--; if (left < right) swap(left, right);// 將2個的位置調換。 } // 2. left 區再和 mid 比 // 如果左側最右邊(右側最左邊)的值比mid大, // 則mid要歸小值區。 left的值不加。 // 即保證:left 區的值都是小的。 if (arr[left] >= arr[end]) swap(left, end); else left++; // left 此時為中間值,位置已被最終確定。無需包含 left。 // 故從 left-1, left + 1 開始。 quick_sort_recursive(start, left - 1); quick_sort_recursive(left + 1, end); } public void sort(int[] arrin) { arr = arrin; quick_sort_recursive(0, arr.length - 1); } }
執行結果:
Creating arrays uses time: 10
氣泡排序: 6024
插入排序: 1234
選擇排序: 1092
快速排序: 20