JAVA大數據數組排序


對於數據排序大家肯定見過不少,選擇排序或者冒泡排序等等,今天我們要做的是快速排序 + 直接插入排序來對大數據(1000萬以上)進行排序,下面我們分別來看看這兩種排序規則

1, 直接插入排序

(1)基本思想:在要排序的一組數中,假設前面(n-1)[n>=2] 個數已經是排

好順序的,現在要把第n個數插到前面的有序數中,使得這n個數

也是排好順序的。如此反復循環,直到全部排好順序。直接插入排序這塊兒是有技巧的,網上很多文章是當前元素和前面已經排序好的元素進行挨個對比,找到位置然后進行數組移位,這樣在數據量很小的情況下沒有什么,但是在大數據面前就顯得比較雞肋了,多次循環很消耗時間資源,那么我們可以采用二分查找法對當前元素的位置進行快速定位,速度就會快很多,處理大數據起來也是比較快的

(2)實例

 

2.快速排序

(1)基本思想:選擇一個基准元素,通常選擇第一個元素或者最后一個元素,通過一趟掃描,將待排序列分成兩部分,一部分比基准元素小,一部分大於等於基准元素,此時基准元素在其排好序后的正確位置,然后再用同樣的方法遞歸地排序划分的兩部分。

(2)實例:

 

好,相信大家看了上面的兩種排序的方法已經心中有數了,那么面對1000萬這樣的大數組來說我們如何處理,現在好多大數據處理想速度快牢記四個字:分而治之,也就是說我們可以將一個很大的數據拆分成多個很小的部分,這樣將計算好的部分結果統計在一起,這樣就可以有效的避免操作大數據對內存CPU硬盤等的消耗,下面來說說我們具體的方案

1、數據拆分

采用快速排序的算法將大數據拆分成兩個(左,右)小部分數據,因為上面快排左側的數據都是小於右側的數據,那么對左側的數據進行排序再對右側的數據進行排序,將結果合並在一起就是我們想要的結果

 

2、排序

將第一步左右側數據進行多次數據拆分之后,會生成多個數據片的,當這個數據片的長度小於固定的長度的時候,這時候就可以對它進行排序了,這里的排序我們采用二分查找+數組移位(效率要比冒泡,選擇排序等快很多)

 

3、合並

當數據快都已經排序好了之后,將排序好的小部分數據合並在一起,那么最終我們的大數組就已經排序完了.

 

 

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中的排序規則是按照數據的不同內部采用了多種不同的排序規則,但是大體來說思路是一樣的,對知識的不斷探索和學習是進階的必要條件,不要傻乎乎的再用冒泡排序了

  

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM