java-排序演算法-未完
阿新 • • 發佈:2019-01-01
再java中經常需要對資料進行排序,一個好的排序演算法,可以大大提高程式的效率,最近開始看資料結構與演算法,將自己學習的筆記和心得紀錄下來。
- 氣泡排序
這大概是想我這種新手使用最多的排序方法了,也基本上是唯一能熟練使用的排序演算法,但是在時間上可以說是相當慢了。由於這個比較簡單,原理什麼的都不重要了,忽略。
private static void sortByBubble(Integer[] array) { Date date = new Date(); for (int i = 0; i < array.length - 1; i++) { for (int j = i + 1; j < array.length; j++) { if (array[i] > array[j]) { int m = array[j]; array[j] = array[i]; array[i] = m; } } } Date end = new Date(); long l = (end.getTime() - date.getTime()); System.out.println("用時:" + l + "毫秒"); }
- 選擇排序
假設第一個為最小值,並用變數min記錄下標,從下一個開始和這個比較,如果比它小,則將min換為這個數的下標,
一輪迴圈結束,則交換一個位置,開始第二輪,這樣雖然比較次數依然是 n*n /2,但交換的次數從O(N*N) 減少到了O(N),在數量比較大時,相比冒泡,速度就會有明顯的提升。private static void sortByChoose(Integer[] array) { Date date = new Date(); int min; for (int i = 0; i < array.length; i++) { min = i; for (int j = i + 1; j < array.length; j++) { if (array[j] < array[min]) { min = j; } } int m = array[i]; array[i] = array[min]; array[min] = m; } Date end = new Date(); long l = (end.getTime() - date.getTime()); System.out.println("選擇排序用時:" + l + " 毫秒"); }
- 選擇排序的優化
有上面可以推出優化版本,我們直接同時將最大和最小都找出來,這樣就能減少一般的迴圈次數。private static void sortByChoose2(Integer[] array) { Date date = new Date(); int min, max; for (int i = 0; i < array.length >> 1; i++) { min = i; max = array.length - 1 - i; for (int j = i + 1; j < array.length - i ; j++) { if (array[j] < array[min]) { min = j; } if(array[j] > array[max]){ max = j; } } int s = array[i]; array[i] = array[min]; array[min] = s; int m = array[array.length - 1 - i]; array[array.length - 1 - i] = array[max]; array[max] = m; } Date end = new Date(); long l = (end.getTime() - date.getTime()); System.out.println("選擇排序2用時:" + l + " 毫秒"); }
上面三個在資料量為:150000 條的時間
- 插入排序
預設左邊都是已經排好序的,接下來就是將右邊的數一個一個的插到已經排好的序列中。
首先需要一個臨時變數存放即將插入的這個數,然後依次從有序部分右邊開始向左比較,如何該數一直大/小,則持續移動陣列,直到找到應該插入的位置。這個表述有些繞,我們還是看程式碼,或者直接看書《資料結構與演算法》private static void sortByInsert(Integer[] array) { print(array); Date date = new Date(); for (int i = 1; i < array.length; i++) { int temp = array[i]; //存放帶插入的數 int foot; // 應該插入位置的下標 // 從有序部分的最右邊開始查詢 temp 的存放位置 for (foot = i; foot > 0; foot--) { // 如果上一個 大於 temp ,則將陣列右移一位 if (array[foot - 1] > temp) { array[foot] = array[foot - 1]; } else { break; } } //將該數放到合適的位置 array[foot] = temp; } Date end = new Date(); long l = (end.getTime() - date.getTime()); print(array); System.out.println("插入排序用時:" + l + " 毫秒"); }
當然我們也可以換一個寫法,讓程式碼看起來更簡潔
private static void sortByInsert2(Integer[] array) { print(array); Date date = new Date(); for (int i = 1; i < array.length; i++) { int temp = array[i]; //存放帶插入的數 int foot = i; // 應該插入位置的下標 while (foot > 0 && array[foot - 1] > temp) { array[foot] = array[foot - 1]; foot -- ; } //將該數放到合適的位置 array[foot] = temp; } Date end = new Date(); long l = (end.getTime() - date.getTime()); print(array); System.out.println("插入排序用時:" + l + " 毫秒"); }
思考:既然左邊是有序的,那麼在查詢是為何還要這樣一個一個的遍歷呢?後面會介紹的,在有序的陣列中查詢是,我們還有很多方式優化,比如常見的二分查詢,這樣速度將進一步提高,但我們就現在也能看出插入排序的效率了
- 待續