zoukankan      html  css  js  c++  java
  • 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中的排序规则是按照数据的不同内部采用了多种不同的排序规则,但是大体来说思路是一样的,对知识的不断探索和学习是进阶的必要条件,不要傻乎乎的再用冒泡排序了

      

     

  • 相关阅读:
    codeforces
    hdu
    hdu
    poj 2823
    hdu
    hdu
    hdu
    微信公众号 SDK
    PHP 正则表达式
    注册和登录时的验证码
  • 原文地址:https://www.cnblogs.com/zyl2016/p/6116644.html
Copyright © 2011-2022 走看看