原文出处: 陶邦仁

binarySearch()方法

二分法查找算法,算法思想:当数据量很大适宜采用该方法。采用二分法查找时,数据需是排好序的。 基本思想:假设数据是按升序排序的,对于给定值x,从序列的中间位置开始比较,如果当前位置值等于x,则查找成功;若x小于当前位置值,则在数列的前半段中查找;若x大于当前位置值则在数列的后半段中继续查找,直到找到为止。

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

sort()方法

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

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

sort()方法

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

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

sort()方法

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

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

http://www.importnew.com/19952.html#comment-499513

深入JDK源码之Arrays类中的排序查找算法(转)的更多相关文章

  1. JDK源码之Integer类分析

    一 简介 Integer是int基本类型的包装类,同样继承了Number类,实现了Comparable接口,String类中的一些转化方法就使用了Integer类中的一些API,且fianl修饰不可继 ...

  2. JDK源码之String类解析

    一 概述 String由final修饰,是不可变类,即String对象也是不可变对象.这意味着当修改一个String对象的内容时,JVM不会改变原来的对象,而是生成一个新的String对象 主要考虑以 ...

  3. JDK源码之Double类&Float类分析

    一 概述 Double 类是基本类型double的包装类,fainl修饰,在对象中包装了一个基本类型double的值.Double继承了Number抽象类,具有了转化为基本double类型的功能. 此 ...

  4. JDK源码之AbstractStringBuilder类分析

    一 概述 二 实现接口 AbstractStringBuilder实现了两个接口: Appendable 概述: Appendable的实现类的对象可以附加字符序列和值. 要追加的字符应该是Unico ...

  5. JDK源码之Byte类分析

    一 简介 byte,即字节,由8位的二进制组成.在Java中,byte类型的数据是8位带符号的二进制数,以二进制补码表示的整数 取值范围:默认值为0,最小值为-128(-2^7);最大值是127(2^ ...

  6. JDK源码之Boolean类分析

    一 简介 boolean类型的封装类,将基本类型为boolean的值包装在一个对象中,实现序列化接口,和Comparable接口 额外提供了许多便捷方法,比较简单,直接贴代码分析 二 源码分析 //t ...

  7. jdk源码理解-String类

    String类的理解 简记录一下对于jdk的学习,做一下记录,会持续补充,不断学习,加油 1.String的hash值的计算方法. hash值的计算方法多种多样,jdk中String的计算方法如下,比 ...

  8. Activiti源码:ActivitiEventSupport类中eventListeners的设计

    ActivitiEventSupport类成员eventListeners是使用CopyOnWriteArrayList实现的. public ActivitiEventSupport() { eve ...

  9. jdk源码阅读-Object类

    native 关键字 private static native void registerNatives(); static { registerNatives(); } public final ...

随机推荐

  1. 手动修改VisualStudio IISExpress的配置

    <VisualStudio> <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}"> ...

  2. spss

    编辑 SPSS(Statistical Product and Service Solutions),“统计产品与服务解决方案”软件.最初软件全称为“社会科学统计软件包” (SolutionsStat ...

  3. Correlation rule tuning

    Lots of organizations are deploying SIEM systems either to do their due diligence or because it’s pa ...

  4. python+opencv

    $cd numpy $ sudo python setup.py build $ sudo python setup.py installRunning from numpy source direc ...

  5. [用UpdateLayeredWindow实现任意异形窗口]

    前面提到,我们可以用SetWindowRgn或SetLayeredWindowAttributes实现不规则以及半透明的效果 对于SetWindowRgn,它通过一个Rgn来设置区域,这个Rgn一般可 ...

  6. 运行于64操作系统上的C#客户端通过WCF访问Oracle数据库不兼容问题

    运行平台: Windows 7  64位操作系统 运行环境: IIS 7 编程语言:C# 数据库: 32位的Oracle 10g 运行原因:64位操作系统C#客户端程序通过WCF访问ORACLE数据库 ...

  7. [置顶] JDK-Future 模式和实现

    最近的项目用到了多线程,发现java.util.concurrent.Future蛮好用的. 像平时,写多线程一般使用Thread/Runnable,直接扔给线程池执行就好了.但是遇到了一些需要获取线 ...

  8. Java基础--finalize()方法

    原理: 一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法,并在下一次垃圾回收动作发生时,才会真正回收对象占用的内存. 用途: 1)释放通过某种创建对象方式以外的方式为对 ...

  9. ubuntu中彻底删除nginx

    1.先执行一下命令: 1.1 删除nginx,–purge包括配置文件 sudo apt-get --purge remove nginx 1.2 自动移除全部不使用的软件包 sudo apt-get ...

  10. new[] class deconstructor

    Class class(); Class *class1=new class; class1=&class; delete class1;   // Assert 指针指向的是一个栈中的对象, ...