Arrays排序原理

Java Arrays排序原理

计数排序源码

(short为例)

for (int i = left - 1; ++i <= right;count[a[i] - Short.MIN_VALUE]++);

for (int i = NUM_SHORT_VALUES, k = right + 1; k > left; ) {

while (count[--i] == 0);

short value = (short) (i + Short.MIN_VALUE);

int s = count[i];

do {

a[--k] = value;

} while (--s > 0);

}

插入排序源码

(int为例)

/*传统插排(无哨兵Sentinel)

* 遍历

* 循环向左比较(

*/

for (int i = left, j = i; i < right; j = ++i) {

int ai = a[i + 1];

while (ai < a[j]) {

a[j + 1] = a[j];

if (j-- == left) {

break;

}

}

a[j + 1] = ai;

}

} else {

//如果一开始就是排好序的——直接返回

do {

if (left >= right) {

return;

}

} while (a[++left] >= a[left - 1]);

//优化插排(以两个为单位遍历,大的元素充当哨兵,以减少小的元素循环向左比较的范围)

for (int k = left; ++left <= right; k = ++left) {

int a1 = a[k], a2 = a[left];

if (a1 < a2) {

a2 = a1; a1 = a[left];

}

while (a1 < a[--k]) {

a[k + 2] = a[k];

}

a[++k + 1] = a1;

while (a2 < a[--k]) {

a[k + 1] = a[k];

}

a[k + 1] = a2;

}

//确保最后一个元素被排序

int last = a[right];

while (last < a[--right]) {

a[right + 1] = a[right];

}

a[right + 1] = last;

}

return;

快排源码

(int为例)

// 快排阈值是286 其7分之一小于等于1/8+1/64+1

int seventh = (length >> 3) + (length >> 6) + 1;

// 获取分成7份的五个中间点

int e3 = (left + right) >>> 1; // The midpoint

int e2 = e3 - seventh;

int e1 = e2 - seventh;

int e4 = e3 + seventh;

int e5 = e4 + seventh;

// 保证中间点的元素从小到大排序

if (a[e2] < a[e1]) {

int t = a[e2]; a[e2] = a[e1]; a[e1] = t; }

if (a[e3] < a[e2]) {

int t = a[e3]; a[e3] = a[e2]; a[e2] = t;

if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }

}

if (a[e4] < a[e3]) {

int t = a[e4]; a[e4] = a[e3]; a[e3] = t;

if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;

if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }

}

}

if (a[e5] < a[e4]) {

int t = a[e5]; a[e5] = a[e4]; a[e4] = t;

if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;

if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;

if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }

}

}

}

// Pointers

int less = left; // The index of the first element of center part

int great = right; // The index before the first element of right part

//点彼此不相等——分三段快排,否则分两段

if (a[e1] != a[e2] && a[e2] != a[e3] && a[e3] != a[e4] && a[e4] != a[e5]) {

/*

* Use the second and fourth of the five sorted elements as pivots.

* These values are inexpensive approximations of the first and

* second terciles of the array. Note that pivot1 <= pivot2.

*/

int pivot1 = a[e2];

int pivot2 = a[e4];

/*

* The first and the last elements to be sorted are moved to the

* locations formerly occupied by the pivots. When partitioning

* is complete, the pivots are swapped back into their final

* positions, and excluded from subsequent sorting.

*/

a[e2] = a[left];

a[e4] = a[right];

while (a[++less] < pivot1);

while (a[--great] > pivot2);

/*

* Partitioning:

*

* left part center part right part

* +--------------------------------------------------------------+

* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |

* +--------------------------------------------------------------+

* ^ ^ ^

* | | |

* less k great

*/

outer:

for (int k = less - 1; ++k <= great; ) {

int ak = a[k];

if (ak < pivot1) { // Move a[k] to left part

a[k] = a[less];

/*

* Here and below we use "a[i] = b; i++;" instead

* of "a[i++] = b;" due to performance issue.

*/

a[less] = ak;

++less;

} else if (ak > pivot2) { // Move a[k] to right part

while (a[great] > pivot2) {

if (great-- == k) {

break outer;

}

}

if (a[great] < pivot1) { // a[great] <= pivot2

a[k] = a[less];

a[less] = a[great];

++less;

} else { // pivot1 <= a[great] <= pivot2

a[k] = a[great];

}

/*

* Here and below we use "a[i] = b; i--;" instead

* of "a[i--] = b;" due to performance issue.

*/

a[great] = ak;

--great;

}

}

// Swap pivots into their final positions

a[left] = a[less - 1]; a[less - 1] = pivot1;

a[right] = a[great + 1]; a[great + 1] = pivot2;

// Sort left and right parts recursively, excluding known pivots

sort(a, left, less - 2, leftmost);

sort(a, great + 2, right, false);

/*

* If center part is too large (comprises > 4/7 of the array),

* swap internal pivot values to ends.

*/

if (less < e1 && e5 < great) {

/*

* Skip elements, which are equal to pivot values.

*/

while (a[less] == pivot1) {

++less;

}

while (a[great] == pivot2) {

--great;

}

/*

* Partitioning:

*

* left part center part right part

* +----------------------------------------------------------+

* | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |

* +----------------------------------------------------------+

* ^ ^ ^

* | | |

* less k great

*

* Invariants:

*

* all in (*, less) == pivot1

* pivot1 < all in [less, k) < pivot2

* all in (great, *) == pivot2

*

* Pointer k is the first index of ?-part.

*/

outer:

for (int k = less - 1; ++k <= great; ) {

int ak = a[k];

if (ak == pivot1) { // Move a[k] to left part

a[k] = a[less];

a[less] = ak;

++less;

} else if (ak == pivot2) { // Move a[k] to right part

while (a[great] == pivot2) {

if (great-- == k) {

break outer;

}

}

if (a[great] == pivot1) { // a[great] < pivot2

a[k] = a[less];

/*

* Even though a[great] equals to pivot1, the

* assignment a[less] = pivot1 may be incorrect,

* if a[great] and pivot1 are floating-point zeros

* of different signs. Therefore in float and

* double sorting methods we have to use more

* accurate assignment a[less] = a[great].

*/

a[less] = pivot1;

++less;

} else { // pivot1 < a[great] < pivot2

a[k] = a[great];

}

a[great] = ak;

--great;

}

}

}

// Sort center part recursively

sort(a, less, great, false);

} else { // Partitioning with one pivot

/*

* Use the third of the five sorted elements as pivot.

* This value is inexpensive approximation of the median.

*/

int pivot = a[e3];

/*

* Partitioning degenerates to the traditional 3-way

* (or "Dutch National Flag") schema:

*

* left part center part right part

* +-------------------------------------------------+

* | < pivot | == pivot | ? | > pivot |

* +-------------------------------------------------+

* ^ ^ ^

* | | |

* less k great

*

* Invariants:

*

* all in (left, less) < pivot

* all in [less, k) == pivot

* all in (great, right) > pivot

*

* Pointer k is the first index of ?-part.

*/

for (int k = less; k <= great; ++k) {

if (a[k] == pivot) {

continue;

}

int ak = a[k];

if (ak < pivot) { // Move a[k] to left part

a[k] = a[less];

a[less] = ak;

++less;

} else { // a[k] > pivot - Move a[k] to right part

while (a[great] > pivot) {

--great;

}

if (a[great] < pivot) { // a[great] <= pivot

a[k] = a[less];

a[less] = a[great];

++less;

} else { // a[great] == pivot

/*

* Even though a[great] equals to pivot, the

* assignment a[k] = pivot may be incorrect,

* if a[great] and pivot are floating-point

* zeros of different signs. Therefore in float

* and double sorting methods we have to use

* more accurate assignment a[k] = a[great].

*/

a[k] = pivot;

}

a[great] = ak;

--great;

}

}

/*

* Sort left and right parts recursively.

* All elements from center part are equal

* and, therefore, already sorted.

*/

sort(a, left, less - 1, leftmost);

sort(a, great + 1, right, false);

}

归并排序前置处理

//判断结构是否适合归并排序

int[] run = new int[MAX_RUN_COUNT + 1];

int count = 0; run[0] = left;

// Check if the array is nearly sorted

for (int k = left; k < right; run[count] = k) {

if (a[k] < a[k + 1]) { // ascending

while (++k <= right && a[k - 1] <= a[k]);

} else if (a[k] > a[k + 1]) { // descending

while (++k <= right && a[k - 1] >= a[k]);

for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {

int t = a[lo]; a[lo] = a[hi]; a[hi] = t;

}

} else {

//连续MAX_RUN_LENGTH(33)个相等元素,使用快排

for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {

if (--m == 0) {

sort(a, left, right, true);

return;

}

}

}

//count达到MAX_RUN_LENGTH,使用快排

if (++count == MAX_RUN_COUNT) {

sort(a, left, right, true);

return;

}

}

// Check special cases

// Implementation note: variable "right" is increased by 1.

if (run[count] == right++) { // The last run contains one element

run[++count] = right;

} else if (count == 1) { // The array is already sorted

return;

}

归并排序源码

(int为例)

byte odd = 0;

for (int n = 1; (n <<= 1) < count; odd ^= 1);

// Use or create temporary array b for merging

int[] b; // temp array; alternates with a

int ao, bo; // array offsets from 'left'

int blen = right - left; // space needed for b

if (work == null || workLen < blen || workBase + blen > work.length) {

work = new int[blen];

workBase = 0;

}

if (odd == 0) {

System.arraycopy(a, left, work, workBase, blen);

b = a;

bo = 0;

a = work;

ao = workBase - left;

} else {

b = work;

ao = 0;

bo = workBase - left;

}

// Merging

for (int last; count > 1; count = last) {

for (int k = (last = 0) + 2; k <= count; k += 2) {

int hi = run[k], mi = run[k - 1];

for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {

if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {

b[i + bo] = a[p++ + ao];

} else {

b[i + bo] = a[q++ + ao];

}

}

run[++last] = hi;

}

if ((count & 1) != 0) {

for (int i = right, lo = run[count - 1]; --i >= lo;

b[i + bo] = a[i + ao]

);

run[++last] = right;

}

int[] t = a; a = b; b = t;

int o = ao; ao = bo; bo = o;

}

java数组原理_Java数组排序原理相关推荐

  1. java 数组 指针_java指针数组的使用

    1,一直都在学java是没有指针的,让我纠结的是java指针确实是存在的,java数组就是真正的指针. 以为C语言老师说过C语言里数组就是指针,但是我感觉这句话用在C语言里不是很严谨,而用在java里 ...

  2. java 数组 树_java使用顺序数组实现二叉树

    顺序数组实现二叉树 实现原理 对于下标为index的节点其满足 1.左孩子节点的下标为2index+1 2.右孩子节点的下标为2index+2 代码实现 package tree; public cl ...

  3. java 数组 反射_java数组的反射

    java数组的反射,有一个JAVA API类可以运用:java.lang.reflect.Array 具体应用: 1:判断一个对象是否是数组: int arr[] = {1,2,3}; Class c ...

  4. java数组缓冲_java – 何时使用数组,缓冲区或直接缓冲区

    题 在编写用于OpenGL库的Matrix类时,我遇到了使用Java数组或Buffer策略来存储数据的问题(JOGL为Matrix操作提供直接缓冲区副本).为了分析这一点,我写了一个小型性能测试程序, ...

  5. Java数组参考_Java数组

    数组变量 VS 数组对象 先看一例子: int[] primitiveArray; //在栈中声明了一个引用变量,暂时还没指向任何对象 primitiveArray = new int[5]; //在 ...

  6. java 数组写法_java书写、数据类型、数组定义

    这里只记录java与php.javascript不同的地方,相同的地方就不赘述了. 1.java文件源码为以.java为后缀的文件,字节码文件是以.class为后缀的文件. 2.写好一个java源码之 ...

  7. java数组 方法_Java数组的十大方法

    Java数组的十大方法 以下是Java Array的前10种方法.他们是来自stackoverflow的投票最多的问题. 0.声明一个数组 String[] aArray = new String[5 ...

  8. java 数组效率_java数组复制的四种方法效率对比

    有关数组的基础知识,有很多方面,比方说初始化,引用,遍历,以及一维数组和二维数组,今天我们先看看数组复制的有关内容. 来源于牛客网的一道选择题: JAVA语言的下面几种数组复制方法中,哪个效率最高? ...

  9. java 数组成员_java 数组中含有

    <数据结构与抽象:Java语言描述(原书第4版)>一2.2.1 可变大小数组 本节书摘来华章计算机<数据结构与抽象:Java语言描述(原书第4版)>一书中的第2章 ,第2.2. ...

最新文章

  1. memcpy()内存拷贝和赋值操作效率测试
  2. 为什么不能在SQL拼接模糊匹配符号
  3. pyinstaller打包exe在其他机器无法运行_详解pyinstaller selenium python3 chrome打包问题!解决率100%...
  4. maven项目不编译xml文件
  5. 激发你的灵感:16个精美视差效果网页设计作品
  6. C# 转繁体转简体转拼音,超级文本大转换
  7. MIPCache 域名升级
  8. 在一个禁止离婚的国家结婚
  9. 从头开始建立神经网络翻译及扩展
  10. 2021-07-06-Intellij IDEA新建项目时JDK以及模块语言等级(language level)默认为1.8或1.5,每次创建新项目都需要重新更改
  11. 《三国志》生僻人名读法集(zz)
  12. STL --- UVA 123 Searching Quickly
  13. Xiaomi Civi即将发布 雷军:宽度仅71.5mm 刚刚好的握持感
  14. 【已解决】报异常:java.lang.ArithmeticException: / by zero
  15. 多进程——守护进程例子
  16. etherboot无盘启动
  17. 1计算机组成及作用是什么,如何理解计算机组成和计算机体系结构?
  18. win10系统镜像下载及在VMware虚拟机上创建win10虚拟机
  19. 牛客网 2018校招真题 吉比特 最大差值
  20. python语言工具_可爱的 Python

热门文章

  1. 触发器如何通知websocket_「Web应用架构」如何扩展WebSockets
  2. char强制类型转换为int_彻底理解Java中的基本数据类型转换(自动、强制、提升)...
  3. c语言人事管理系统,c语言人事管理系统
  4. css3弧形跑道效果_【Tableau 图表】你是不是真的需要一个跑道图呢?
  5. linux 常用压缩格式,Linux常见压缩格式之压缩与解压
  6. 针织布横条疵点解决方案
  7. 06-4.部署高可用 kube-scheduler 集群
  8. HTTPS详解SSL/TLS
  9. MySQL与Oracle的语法区别详细对比 (转)
  10. pcDuino的linux移植五GPIO驱动开发