淺談排序演算法的效率(二)—(Java筆記)
阿新 • • 發佈:2018-12-13
首先:咱也借用一下網上的那張XXX的圖,咯!在下面:
接下來,就是咱的驗證時間了(驗證什麼?當然是各種演算法的時間複雜度比較咯),沒什麼好說的了,直接上碼吧。
程式碼實現:
import java.util.Arrays; public class SortSummary { /** * 各排序演算法效率比較 */ // 1、氣泡排序 int[] bubbleSort(int[] data) { for (int i = 1; i < data.length; i++) { for (int j = 0; j < data.length - i; j++) { if (data[j] > data[j + 1]) { int temp = data[j + 1]; data[j + 1] = data[j]; data[j] = temp; } } } return data; } // 2、快速排序 int[] quickSort(int[] data, int start, int end) { int tstart = start; int tend = end; int base = data[tstart]; while (tstart < tend) { while (tstart < tend && data[tend] >= base) { tend--; } if (data[tend] < base) { int temp = data[tstart]; data[tstart] = data[tend]; data[tend] = temp; } while (tstart < tend && data[tstart] <= base) { tstart++; } if (data[tstart] > base) { int temp = data[tend]; data[tend] = data[tstart]; data[tstart] = temp; } } if (tstart > start) { quickSort(data, start, tstart - 1); } if (tend < end) { quickSort(data, tend + 1, end); } return data; } // 3、選擇排序 int[] selectSort(int[] data) { for (int i = 0; i < data.length - 1; i++) { int index = i; for (int j = i + 1; j < data.length; j++) { if (data[j] < data[index]) { index = j; } } int temp = data[i]; data[i] = data[index]; data[index] = temp; } return data; } // 4、堆排序 void heapSortUtil1(int[] data, int root, int size) { int rootNode = root; int leftNode = 2 * rootNode + 1; int rightNode = 2 * rootNode + 2; if (leftNode <= size) { if (data[rootNode] < data[leftNode]) { rootNode = leftNode; } } if (rightNode <= size) { if (data[rootNode] < data[rightNode]) { rootNode = rightNode; } } if (rootNode != root) { int temp = data[root]; data[root] = data[rootNode]; data[rootNode] = temp; heapSortUtil1(data, rootNode, size); } } void heapSortUtil2(int[] data, int size) { for (int i = data.length - 1; i >= 0; i--) { heapSortUtil1(data, i, size); } } int[] heapSort(int[] data) { for (int i = 0; i < data.length; i++) { heapSortUtil2(data, data.length - i - 1); int temp = data[0]; data[0] = data[data.length - i - 1]; data[data.length - i - 1] = temp; } return data; } // 5、插入排序 int[] insertSort(int[] data) { for (int i = 1; i < data.length; i++) { int index = data[i]; int j = i; for (j -= 1; j >= 0 && index < data[j]; j--) { data[j + 1] = data[j]; } data[j + 1] = index; } return data; } // 6、希爾排序 int[] shellSort(int[] data) { for(int k=data.length/2;k>0;k/=2){ for (int i = k; i < data.length; i++) { int index = data[i]; int j = i; for (j -= k; j >= 0 && index < data[j]; j-=k) { data[j + k] = data[j]; } data[j + k] = index; } } return data; } public static void main(String[] args) { // 各排序演算法效率比較 long start;// 記錄演算法開始的時間 long end;// 記錄演算法結束的時間 SortSummary ss = new SortSummary(); int[] data = new int[10000]; // 隨機生成10000個序列保存於陣列中 for (int i = 0; i < data.length; i++) { data[i] = (int) (Math.random() * 10000); } int[] data1=new int[10000]; int[] data2=new int[10000]; int[] data3=new int[10000]; int[] data4=new int[10000]; int[] data5=new int[10000]; int[] data6=new int[10000]; //複製陣列,java中對陣列的複製只能是System.arraycopy System.arraycopy(data, 0, data1, 0, data.length); System.arraycopy(data, 0, data2, 0, data.length); System.arraycopy(data, 0, data3, 0, data.length); System.arraycopy(data, 0, data4, 0, data.length); System.arraycopy(data, 0, data5, 0, data.length); System.arraycopy(data, 0, data6, 0, data.length); System.out.println(Arrays.toString(data)); //------------------------------------------------------------------ // 1、氣泡排序 start = System.currentTimeMillis(); data1 = ss.bubbleSort(data1); end = System.currentTimeMillis(); //System.out.println(Arrays.toString(data1)); System.out.println("氣泡排序 用時:" + (end - start)); // 2、快速排序 start = System.currentTimeMillis(); data2 = ss.quickSort(data2, 0, data.length - 1); end = System.currentTimeMillis(); // System.out.println(Arrays.toString(data2)); System.out.println("快速排序 用時:" + (end - start)); // 3、選擇排序 start = System.currentTimeMillis(); data3 = ss.selectSort(data3); end = System.currentTimeMillis(); // System.out.println(Arrays.toString(data3)); System.out.println("選擇排序 用時:" + (end - start)); // 4、堆排序 start = System.currentTimeMillis(); data4= ss.heapSort(data4); end = System.currentTimeMillis(); // System.out.println(Arrays.toString(data4)); System.out.println("堆排序 用時:" + (end - start)); // 5、插入排序 start = System.currentTimeMillis(); data5 = ss.insertSort(data5); end = System.currentTimeMillis(); //System.out.println(Arrays.toString(data5)); System.out.println("插入排序 用時:" + (end - start)); // 6、希爾排序 start = System.currentTimeMillis(); data6 = ss.shellSort(data6); end = System.currentTimeMillis(); //System.out.println(Arrays.toString(data6)); System.out.println("希爾排序 用時:" + (end - start)); } }
當10000個數據為隨機資料時,執行看看:
// 隨機生成10000個序列保存於陣列中
for (int i = 0; i < data.length; i++) {
data[i] = (int)(Math.random()*10000);
}
執行結果:因為資料量太大(10000個),就不輸出資料了,直接看結果吧
氣泡排序 用時:484
快速排序 用時:8
選擇排序 用時:109
堆排序 用時:572
插入排序 用時:142
希爾排序 用時:20
多次測試,結果表示,當資料的分佈完全隨機(沒有任何規律時),快速排序的效率是最高的,而堆排序的效率最低,這也可以理解,因為堆排序本就是樹結構的排序方式,排序中用到了遞迴,當資料量很大的時候,遞迴層次更深入,不斷地呼叫自身方法,往棧中壓入資料,導致效率低下。
當10000個數據為有序(升序)資料時:
// 升序生成10000個序列保存於陣列中
for (int i = 0; i < data.length; i++) {
data[i] = i;
}
執行結果:
氣泡排序 用時:82
快速排序 用時:97
選擇排序 用時:75
堆排序 用時:642
插入排序 用時:2
希爾排序 用時:15
多次測試,結果表示當資料已有順序且為升序時,插入排序的效率是最高的,堆排序是一如既往的低啊。
當10000個數據為有序(降序)資料時:
// 降序生成10000個序列保存於陣列中 for (int i = 0; i < data.length; i++) { data[i] =data.length-i-1; } 執行結果: 氣泡排序 用時:373 快速排序 用時:287 選擇排序 用時:150 堆排序 用時:682 插入排序 用時:265 希爾排序 用時:18
多次測試,結果表示當資料已有順序且為降序時,希爾排序的效率是最高的,此時的插入排序反而不是最佳選擇。