`
m635674608
  • 浏览: 5032279 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

深入JDK源代码之Arrays类中的排序查找算法

 
阅读更多

java.util.Arrays类。这个类是个数组工具类。主要提供方法sort(),fill(),binarySearch(),还有数组复制等方法。打开源文件,刚超过4千行,不过包括很多注释,那么我在这里主要讲讲这里面涉及的排序算法和查找算法。
  一、binarySearch()方法,二分法查找算法, 算法思想:当数据量很大适宜采用该方法。采用二分法查找时,数据需是排好序的。 基本思想:假设数据是按升序排序的,对于给定值x,从序列的中间位置开始比较,如果当前位置值等于x,则查找成功;若x小于当前位置值,则在数列的前半段 中查找;若x大于当前位置值则在数列的后半段中继续查找,直到找到为止。
 

Java代码  收藏代码
  1. //针对int类型数组的二分法查找,key为要查找数的下标  
  2.     private static int binarySearch0(int[] a, int fromIndex, int toIndex,  
  3.                      int key) {  
  4.     int low = fromIndex;  
  5.     int high = toIndex - 1;  
  6.     while (low <= high) {  
  7.         int mid = (low + high) >>> 1;//无符号左移一位,相当于除以二  
  8.         int midVal = a[mid];  
  9.   
  10.         if (midVal < key)  
  11.         low = mid + 1;  
  12.         else if (midVal > key)  
  13.         high = mid - 1;  
  14.         else  
  15.         return mid; // key found  
  16.     }  
  17.     return -(low + 1);  // key not found.  
  18.     }  


二、sort()方法针对引用类型数组采取的算法是归并排序。算法思想:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
 

Java代码  收藏代码
  1. private static final int INSERTIONSORT_THRESHOLD = 7;//插入排序门槛  
  2.   public static void sort(Object[] a) {  
  3.        Object[] aux = (Object[])a.clone();  
  4.        mergeSort(aux, a, 0, a.length, 0);  
  5.    }  
  6.    //归并排序  
  7.    private static void mergeSort(Object[] src,  
  8.               Object[] dest,  
  9.               int low,  
  10.               int high,  
  11.               int off) {  
  12.        int length = high - low;  
  13.   
  14.        if (length < INSERTIONSORT_THRESHOLD) { //若数组长度小于7,则用冒泡排序  
  15.            for (int i=low; i<high; i++)  
  16.                for (int j=i; j>low &&  
  17.          ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)  
  18.                    swap(dest, j, j-1);  
  19.            return;  
  20.        }  
  21.   
  22.        // Recursively sort halves of dest into src  
  23.        int destLow  = low;  
  24.        int destHigh = high;  
  25.        low  += off;  
  26.        high += off;  
  27.        int mid = (low + high) >>> 1//无符号左移一位,  
  28.        mergeSort(dest, src, low, mid, -off);  
  29.        mergeSort(dest, src, mid, high, -off);  
  30.   
  31.        // If list is already sorted, just copy from src to dest.  This is an  
  32.        // optimization that results in faster sorts for nearly ordered lists.  
  33.        if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {  
  34.            System.arraycopy(src, low, dest, destLow, length);  
  35.            return;  
  36.        }  
  37.   
  38.        // Merge sorted halves (now in src) into dest  
  39.        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {  
  40.            if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)  
  41.                dest[i] = src[p++];  
  42.            else  
  43.                dest[i] = src[q++];  
  44.        }  
  45.    }  


三、sort()方法采取的是快速排序算法,算法思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
  

Java代码  收藏代码
  1. /** 
  2.     * Swaps x[a] with x[b]. 
  3.     */  
  4. private static void swap(int x[], int a, int b) {  
  5. int t = x[a];  
  6. x[a] = x[b];  
  7. x[b] = t;  
  8.    }  
  9. public static void sort(int[] a) {  
  10. sort1(a, 0, a.length);  
  11.    }  
  12.   
  13. private static int med3(int x[], int a, int b, int c) {//找出三个中的中间值  
  14. return (x[a] < x[b] ?  
  15.     (x[b] < x[c] ? b : x[a] < x[c] ? c : a) :  
  16.     (x[b] > x[c] ? b : x[a] > x[c] ? c : a));  
  17.    }  
  18.   
  19.   /** 
  20.     * Sorts the specified sub-array of integers into ascending order. 
  21.     */  
  22.  private static void sort1(int x[], int off, int len) {  
  23. // Insertion sort on smallest arrays  
  24. if (len < 7) {//采用冒泡排序  
  25.     for (int i=off; i<len+off; i++)  
  26.     for (int j=i; j>off && x[j-1]>x[j]; j--)  
  27.         swap(x, j, j-1);  
  28.     return;  
  29. }  
  30.    //采用快速排序  
  31. // Choose a partition element, v  
  32. int m = off + (len >> 1);       // Small arrays, middle element  
  33. if (len > 7) {  
  34.     int l = off;  
  35.     int n = off + len - 1;  
  36.     if (len > 40) {        // Big arrays, pseudomedian of 9  
  37.     int s = len/8;  
  38.     l = med3(x, l,     l+s, l+2*s);  
  39.     m = med3(x, m-s,   m,   m+s);  
  40.     n = med3(x, n-2*s, n-s, n);  
  41.     }  
  42.     m = med3(x, l, m, n); // Mid-size, med of 3  
  43. }  
  44. int v = x[m];  
  45.   
  46. // Establish Invariant: v* (<v)* (>v)* v*  
  47. int a = off, b = a, c = off + len - 1, d = c;  
  48. while(true) {  
  49.     while (b <= c && x[b] <= v) {  
  50.     if (x[b] == v)  
  51.         swap(x, a++, b);  
  52.     b++;  
  53.     }  
  54.     while (c >= b && x[c] >= v) {  
  55.     if (x[c] == v)  
  56.         swap(x, c, d--);  
  57.     c--;  
  58.     }  
  59.     if (b > c)  
  60.     break;  
  61.     swap(x, b++, c--);  
  62. }  
  63.   
  64. // Swap partition elements back to middle  
  65. int s, n = off + len;  
  66. s = Math.min(a-off, b-a  );  vecswap(x, off, b-s, s);  
  67. s = Math.min(d-c,   n-d-1);  vecswap(x, b,   n-s, s);  
  68.   
  69. // Recursively sort non-partition-elements  
  70. if ((s = b-a) > 1)  
  71.     sort1(x, off, s);  
  72. if ((s = d-c) > 1)  
  73.     sort1(x, n-s, s);  
  74.    }  


四、针对double,float类型数组排序的sort()方法,采取了先把所有的数组元素值为-0.0d的转换成0.0d,再利用快速排序排好序,最后再还原。
  

Java代码  收藏代码
  1. public static long doubleToRawLongBits(double value)根据 IEEE 754 浮点“双精度格式”位布局,返回指定浮点值的表示形式,并保留 NaN 值。   
  2. 第 63 位(掩码 0x8000000000000000L 选定的位)表示浮点数的符号。第 62-52 位(掩码 0x7ff0000000000000L 选定的位)表示指数。第 51-0 位(掩码 0x000fffffffffffffL 选定的位)表示浮点数的有效数字(有时也称为尾数)。   
  3.   
  4. 如果参数是正无穷大,则结果为 0x7ff0000000000000L。   
  5.   
  6. 如果参数是负无穷大,则结果为 0xfff0000000000000L。   
  7.   
  8. 如果参数是 NaN,则结果是表示实际 NaN 值的 long 整数。与 doubleToLongBits 方法不同,doubleToRawLongBits 并没有压缩那些将 NaN 编码为一个“规范的”NaN 值的所有位模式。   
  9.   
  10. 在所有情况下,结果都是一个 long 整数,将其赋予 longBitsToDouble(long) 方法将生成一个与 doubleToRawLongBits 的参数相同的浮点值。   
  11.   
  12.   
  13. 参数:  
  14. value - 双精度 (double) 浮点数。   


下面是源代码中的方法:

Java代码  收藏代码
  1. public static void sort(double[] a) {  
  2.     sort2(a, 0, a.length);  
  3.    }  
  4. private static void sort2(double a[], int fromIndex, int toIndex) {  
  5.  //static long doubleToLongBits(double value)   
  6. //根据 IEEE 754 浮点双精度格式 ("double format") 位布局,返回指定浮点值的表示形式。  
  7.      final long NEG_ZERO_BITS = Double.doubleToLongBits(-0.0d);  
  8.      /* 
  9.       * The sort is done in three phases to avoid the expense of using 
  10.       * NaN and -0.0 aware comparisons during the main sort. 
  11.       */  
  12.   
  13.      /* 
  14.       * Preprocessing phase:  Move any NaN's to end of array, count the 
  15.       * number of -0.0's, and turn them into 0.0's. 
  16.       */  
  17.      int numNegZeros = 0;  
  18.      int i = fromIndex, n = toIndex;  
  19.      while(i < n) {  
  20.          if (a[i] != a[i]) {  //这段搞不懂,源代码怪怪的,感觉多此一举  
  21. ouble swap = a[i];  
  22.              a[i] = a[--n];  
  23.              a[n] = swap;  
  24.          } else {  
  25.              if (a[i]==0 && Double.doubleToLongBits(a[i])==NEG_ZERO_BITS) {  
  26.                  a[i] = 0.0d;  
  27.                  numNegZeros++;  
  28.              }  
  29.              i++;  
  30.          }  
  31.      }  
  32.   
  33.      // Main sort phase: quicksort everything but the NaN's  
  34.   sort1(a, fromIndex, n-fromIndex);  
  35.   
  36.      // Postprocessing phase: change 0.0's to -0.0's as required  
  37.      if (numNegZeros != 0) {  
  38.          int j = binarySearch0(a, fromIndex, n, 0.0d); // posn of ANY zero  
  39.          do {  
  40.              j--;  
  41.          } while (j>=0 && a[j]==0.0d);  
  42.   
  43.          // j is now one less than the index of the FIRST zero  
  44.          for (int k=0; k<numNegZeros; k++)  
  45.              a[++j] = -0.0d;  
  46.      }  
  47.  } 

http://zengzhaoshuai.iteye.com/blog/1130376

http://hxraid.iteye.com/blog/665095/

分享到:
评论

相关推荐

    jdk1.7.0_80_x86_32.zip

    - **多路归并排序**:JDK7中的`Arrays.sort()`和`Collections.sort()`方法使用了新的多路归并排序算法,提高了排序性能。 - **Fork/Join框架**:用于并行执行任务,提高计算密集型任务的执行效率。 - **元空间**...

    jdk 1.8.chm

    本篇将围绕"jdk 1.8 api"这一主题,深入探讨Java SDK 1.8中的关键知识点,帮助开发者提升效率,实现更高效、更优雅的代码编写。 1. **Lambda表达式** JDK 1.8引入了Lambda表达式,这是对函数式编程的一大迈进。...

    jdk-7u80-windows-x64.exe

    【标签】"源码软件" 暗示JDK包含的不仅有二进制文件,还可能包括Java语言的源代码,这对于学习和理解Java的内部工作原理非常有帮助。"windows" 表明这是为Windows操作系统设计的版本。"jdk-7" 指的是Java SE(标准版...

    JDK11_DSA_SrcComment:在JDK 11中阅读数据结构和算法(DSA)的注意事项

    "JDK11_DSA_SrcComment"可能是指一个项目或者资源,它专注于分析和解释JDK 11源代码中的数据结构和算法。这个项目可能是为了帮助开发者更好地理解JDK 11中实现的各种内部机制,从而提升编程技能和效率。 JDK(Java ...

    txtSort.zip

    在这个"txtSort"的压缩包中,很可能包含了一个或多个Java源代码文件,用于实现文本文件的排序功能。这些文件可能演示了如何读取文本文件,处理其中的数据(比如字符串或数字),然后进行排序,并可能将排序后的结果...

    JDK 1.5 中文文档.rar

    7. **注解**:提供了一种元数据机制,可以在源代码中添加元信息,用于编译时或运行时的处理,如`@Override`、`@Deprecated`等。 四、反射增强 8. **`java.lang.reflect.ParameterizedType`**:增加了对泛型类型的...

    java 相关问题(二)

    以下是一些关于Java中类排序及其相关的深入知识点: 1. **Java类排序**: - `Comparable`接口:Java中的每个类都可以实现`Comparable`接口,定义自己的比较逻辑。通过实现`compareTo()`方法,可以定义对象之间的...

    JDK1.8版本

    - **javac**:Java编译器,将源代码编译成字节码。 - **jar**:打包工具,可以创建、更新和提取.jar文件。 - **javadoc**:生成API文档的工具。 - **jconsole**:Java监控和管理控制台,用于监控应用程序...

    jdk-7windows-x64.rar

    1. **Java编译器 (javac)**:负责将源代码(.java文件)编译成字节码(.class文件),这是Java程序执行的第一步。 2. **Java虚拟机 (JVM)**:JVM是Java平台的核心,它负责运行编译后的字节码。JDK 7中的JVM在性能和...

    jdk1.7 64位免安装

    3. **多路归并排序**:`Arrays.sort()`方法在Java 7中使用了多路归并排序算法,提高了数组排序的性能。 4. **尝试-with资源**(Try-with-resources):这个新语法结构使得资源管理更加简洁和安全,确保了在finally...

    jdk1.7 7u80 64位

    4. **多路归并排序**:Java 7引入了一个新的并发排序算法,提高了`Arrays.sort()`和`Collections.sort()`的性能。 5. **新文件系统API (NIO.2)**:提供了更高级别的文件操作,如路径、文件属性和异步I/O。 6. **...

    JDK-API-CODE:jdk7 API的源代码,加上了自己的注释

    - **多路归并排序**:在`java.util`包中,JDK7引入了`java.util.Arrays.sort()`方法的改进版,采用了多路归并排序算法,提高了大规模数据排序的性能。 - **try-with-resources**:在`java.lang`包中,新增了`try-...

    java1.8源码-java_jdk1.8:jdk1.8源代码

    Java 1.8 源码是 Java 开发者深入理解 JDK 内部工作原理的重要资源,它揭示了 Java 核心库的实现细节。在 JDK 1.8 版本中,引入了许多重要的更新和优化,包括 Lambda 表达式、Stream API、Date 和 Time API 的改进...

    jdk8新特性详细介绍

    3. **方法引用**:除了Lambda表达式,JDK8还提供了方法引用,它可以直接引用类中的静态方法或者对象实例上的非静态方法,进一步简化了代码。例如,`Arrays.sort(list, Comparator.comparing(Person::getName))`。 4...

    jdk-7u80-windows-x64.zip

    1. **Java编译器 (javac)**:这是JDK的核心组件之一,用于将源代码编译成可执行的Java字节码。在JDK 1.7中,编译器支持新的语法特性,如钻石操作符()和多线程注解(@SafeVarargs)。 2. **Java运行时环境 (JRE)**...

    java程序设计实验报告.pdf

    安装和配置JDK是进行Java编程的第一步,常用命令如`javac`用于编译Java源代码,`java`用于运行已编译的类。 2. **数据类型**:Java有两大类数据类型:基本数据类型(如字节byte、短整型short、整型int、长整型long...

    面试java高级技术总结.pdf

    调试是识别和修复代码错误的过程,Java开发工具(JDK)内置的Java Debugger(JDB)可以帮助进行源代码级别的调试。 4. **集合框架**:集合是Java中存储多个对象的容器,包括接口(如`List`, `Set`, `Map`)和实现...

    java深度历险.pdf

    在某些特定情况下,如算法竞赛的在线评测系统,需要在运行时动态编译Java源代码。JSR 199引入了Java编译器API,允许在JDK 6及更高版本中动态编译Java代码。以下是一个简单的示例,展示了如何使用该API编译"Hello ...

    Java基础资料+重点面试题.pdf

    排序数组时,既可以使用手动实现的排序算法(如冒泡排序),也可以使用Java的Arrays类提供的sort方法进行自动排序。数组的相关知识点也是面试中的常客,包括如何创建和使用数组,以及数组排序和复制的方法。 九、...

Global site tag (gtag.js) - Google Analytics