對於數據排序你們確定見過很多,選擇排序或者冒泡排序等等,今天咱們要作的是快速排序 + 直接插入排序來對大數據(1000萬以上)進行排序,下面咱們分別來看看這兩種排序規則java
(1)基本思想:在要排序的一組數中,假設前面(n-1)[n>=2] 個數已是排算法
好順序的,如今要把第n個數插到前面的有序數中,使得這n個數數組
也是排好順序的。如此反覆循環,直到所有排好順序。直接插入排序這塊兒是有技巧的,網上不少文章是當前元素和前面已經排序好的元素進行挨個對比,找到位置而後進行數組移位,這樣在數據量很小的狀況下沒有什麼,可是在大數據面前就顯得比較雞肋了,屢次循環很消耗時間資源,那麼咱們能夠採用二分查找法對當前元素的位置進行快速定位,速度就會快不少,處理大數據起來也是比較快的dom
(2)實例學習
(1)基本思想:選擇一個基準元素,一般選擇第一個元素或者最後一個元素,經過一趟掃描,將待排序列分紅兩部分,一部分比基準元素小,一部分大於等於基準元素,此時基準元素在其排好序後的正確位置,而後再用一樣的方法遞歸地排序劃分的兩部分。大數據
(2)實例:this
好,相信你們看了上面的兩種排序的方法已經心中有數了,那麼面對1000萬這樣的大數組來講咱們如何處理,如今好多大數據處理想速度快牢記四個字:分而治之,也就是說咱們能夠將一個很大的數據拆分紅多個很小的部分,這樣將計算好的部分結果統計在一塊兒,這樣就能夠有效的避免操做大數據對內存CPU硬盤等的消耗,下面來講說咱們具體的方案spa
一、數據拆分3d
採用快速排序的算法將大數據拆分紅兩個(左,右)小部分數據,由於上面快排左側的數據都是小於右側的數據,那麼對左側的數據進行排序再對右側的數據進行排序,將結果合併在一塊兒就是咱們想要的結果blog
二、排序
將第一步左右側數據進行屢次數據拆分以後,會生成多個數據片的,當這個數據片的長度小於固定的長度的時候,這時候就能夠對它進行排序了,這裏的排序咱們採用二分查找+數組移位(效率要比冒泡,選擇排序等快不少)
三、合併
當數據快都已經排序好了以後,將排序好的小部分數據合併在一塊兒,那麼最終咱們的大數組就已經排序完了.
package ss; import java.util.Arrays; import java.util.Random; public class Sort { //分片數組長度爲多少時,開始排序 public final static int SORT_NUM = 50; //數組的長度 public final static int ARRAY_NUM = 10000000; public static void main(String[] args) { //聲明數組長度 int[] array = new int[ARRAY_NUM]; //生成隨機數據 for (int j = 0; j < ARRAY_NUM; j++) { array[j] = new Random().nextInt(Integer.MAX_VALUE); } //複製數組,採用JDK自帶排序 int[] arrayCopy = new int[ARRAY_NUM]; System.arraycopy(array, 0, arrayCopy, 0, ARRAY_NUM); //數據少的時候能夠看看初始化結果,數據量大,ecplise直接就崩潰了。 //System.out.println("init :"+Arrays.toString(array)); long time1 = System.currentTimeMillis(); sort(array,0,array.length); long time2 = System.currentTimeMillis(); //System.out.println(Arrays.toString(array)); System.out.println(time2 - time1); Arrays.sort(arrayCopy); long time3 = System.currentTimeMillis(); System.out.println(time3 - time2); } public static void sort(int[] array,int begin,int end){ //若排序部門長度小於SORT_NUM if(end - begin<=SORT_NUM){ //循環排序部分的元素 for (int i = begin+1; i < end; i++) { //查找當前元素的位置 int index = findIndex(array[i], begin, i - 1, array); //獲取當前元素 int value = array[i]; //數組移位 System.arraycopy(array, index, array, index + 1, i - index); //將當前數組插入到合適的位置 array[index] = value; } return; } //做爲中間軸參數使用 int temp = array[begin]; //獲取當前的位置 int currentIndex = begin; int left =begin; int right=end-1; while(left<right){ //向右比較 for(;left < right;right--){ if(left < right && array[right]<temp){ swap(array,currentIndex,right); currentIndex = right; left++; break; } } //向左比較 for(;left < right;left++){ if(left < right && array[left]>temp){ swap(array,currentIndex,left); currentIndex = left; right--; break; } } } //左側排序 sort(array,begin,currentIndex+1); //右側排序 sort(array,currentIndex+1,end); } public static void swap(int[] array,int index1,int index2){ int temp = array[index1]; array[index1] = array[index2]; array[index2] = temp; } //二分查找排序 public static int findIndex(int thisval, int from, int to, int[] sortArray) { int index = 0; //當左側數據大於當前數據,返回from的索引 if (sortArray[from] >= thisval) { index = from; return index; } //當右側數據小於當前數據,返回index後面的索引 if (sortArray[to] <= thisval) { index = to + 1; return index; } if (to - from == 1) { return to; } //獲取from和to的中間值 int middle = (to - from) / 2 + from; //判斷當前值在左側仍是右側 if (sortArray[middle] >= thisval) { //左側 return findIndex(thisval, from, middle, sortArray); } else { //右側 return findIndex(thisval, middle, to, sortArray); } } }
看一下最後咱們執行的時間,大約是1000萬條隨機的數據,我門排序的時間的大約是1秒多一些,JDK1.7自帶的Arrays.sort()大約不到1秒,JDK1.7中的排序規則是按照數據的不一樣內部採用了多種不一樣的排序規則,可是大致來講思路是同樣的,對知識的不斷探索和學習是進階的必要條件,不要傻乎乎的再用冒泡排序了