java中常用排序工具类, 使用的算法是什么?什么,怎么还有组合模式参与?
Posted 洪宏鸿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中常用排序工具类, 使用的算法是什么?什么,怎么还有组合模式参与?相关的知识,希望对你有一定的参考价值。
排序我是认真的 🚇
所谓成长就是在人世间这个道场里的一场自我救赎与修行
Java中常用的排序工具类是Arrays.sort()和Collections.sort(),它们底层使用的是基于快速排序(quicksort)算法和归并排序(mergesort)算法的排序算法。
对于Arrays.sort()方法,其底层使用的是经过优化的快速排序算法,它是一种基于分治思想的排序算法,通过不断地把待排序的数组分割成较小的子数组进行递归排序,最终将这些子数组合并起来得到有序的结果。快速排序算法的时间复杂度为O(nlogn),它是目前使用最广泛的排序算法之一。
对于Collections.sort()方法,其底层使用的是归并排序算法,它也是一种基于分治思想的排序算法,它将待排序的数组不断划分成更小的子数组,对每个子数组进行排序后再将它们合并成一个有序的数组。归并排序算法的时间复杂度为O(nlogn),它具有稳定性和适用于大规模数据排序的优点。
需要注意的是,对于小规模数据排序,Arrays.sort()方法采用了插入排序(insertion sort)和选择排序(selection sort)的混合算法进行排序,而Collections.sort()方法则直接使用归并排序算法进行排序。
Arrays.sort()方法采用了一种优化的排序算法 组合模式 1+1>2
没想到吧, 设计模式竟然就在我们身边, 通过将各种排序进行组合, 得到在各个数据量中的优化解,
其实快速在小数据量的情况下, 并不是很快, 如果使用其他排序算法的情况下, 这个时候就要考虑排序算法的时间复杂度, 空间复杂度了
这个时候加上了我们的插入排序跟我们的选择排序, 简直是妙呀
Arrays.sort()方法采用了一种优化的排序算法,对于小规模数据使用了插入排序和选择排序的混合算法进行排序,其源码如下:
private static void sort(int[] a, int left, int right, int[] work, int workBase, int workLen)
// 当数组长度小于某个阈值时,使用插入排序或选择排序进行排序
if (right - left < INSERTION_SORT_THRESHOLD)
insertionSort(a, left, right);
return;
else if (right - left < QUICKSORT_THRESHOLD)
binarySort(a, left, right, left + countRunAndMakeAscending(a, left, right));
return;
// 继续使用快速排序
int pivot = medianOfThree(a, left, left + ((right - left) >> 1), right);
int i = left;
int j = right;
int p = left;
int q = right;
while (true)
if (i <= j)
if (i != j)
if ((j - i) != 1)
swap(a, i, pivot);
if (a[i] <= pivot)
i++;
continue;
swap(a, i, j);
j--;
while (a[j] > pivot)
j--;
while (i < j && a[i] <= pivot)
i++;
if (i < j)
swap(a, i, j);
else
break;
// 将相等的元素移到数组中间
int k = Math.min(i - left, p - left);
vecswap(a, left, i - k, k);
k = Math.min(q - j, right - j - 1);
vecswap(a, i, right - k, k);
// 对剩下的元素继续递归排序
if ((k = i - left) > 1)
sort(a, left, i - 1, work, workBase, workLen);
if ((k = right - j) > 1)
sort(a, j + 1, right, work, workBase, workLen);
可以看到,当待排序的数组长度小于某个阈值(默认为47)时,使用插入排序或选择排序进行排序,否则使用快速排序算法进行排序。
具体来说,当待排序的数组长度小于15时,使用插入排序进行排序;当待排序的数组长度大于等于15且小于47时,使用选择排序进行排序。选择排序的优点是不需要额外的空间来存储排序结果,且由于每次选择最小(或最大)的元素交换到数组的最前面,可以减少后续排序的比较次数。
需要注意的是,虽然插入排序和选择排序在时间复杂度上不如快速排序,但是对于小规模数据排序它们的时间复杂度较低,并且在实际应用中它们的表现可能比快速排序更好。
归并排序算法
归并排序是一种经典的排序算法,它基于分治思想,将待排序的数组分成两个子数组,对每个子数组进行排序后再将它们合并成一个有序的数组。
下面是归并排序的详细实现步骤:
-
分解数组:将待排序的数组从中间分成两个子数组,直到不能再分解为止。
-
排序子数组:对每个子数组进行排序,可以使用递归或非递归的方式。
-
合并数组:将排好序的子数组合并成一个有序的数组。
具体的实现方法可以是:
private static void mergeSort(int[] arr, int left, int right)
if (left < right)
// 1. 分解数组
int mid = (left + right) / 2;
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
// 2. 排序子数组
merge(arr, left, mid, right);
private static void merge(int[] arr, int left, int mid, int right)
// 定义左右两个子数组的开始和结束位置
int leftStart = left;
int leftEnd = mid;
int rightStart = mid + 1;
int rightEnd = right;
// 计算左右两个子数组的长度
int leftLength = leftEnd - leftStart + 1;
int rightLength = rightEnd - rightStart + 1;
// 创建左右两个子数组的临时数组
int[] leftTemp = new int[leftLength];
int[] rightTemp = new int[rightLength];
// 将左右两个子数组复制到临时数组中
for (int i = 0; i < leftLength; i++)
leftTemp[i] = arr[leftStart + i];
for (int j = 0; j < rightLength; j++)
rightTemp[j] = arr[rightStart + j];
// 3. 合并数组
int i = 0;
int j = 0;
int k = leftStart;
while (i < leftLength && j < rightLength)
if (leftTemp[i] < rightTemp[j])
arr[k++] = leftTemp[i++];
else
arr[k++] = rightTemp[j++];
// 将左右两个子数组中剩余的元素复制到原数组中
while (i < leftLength)
arr[k++] = leftTemp[i++];
while (j < rightLength)
arr[k++] = rightTemp[j++];
在实现过程中,需要注意以下几点:
-
在合并数组时,需要使用额外的空间来存储左右两个子数组的临时数组。
-
在合并数组时,需要比较左右两个子数组中的元素,并将较小的元素先放入原数组中。
-
在合并数组时,需要将左右两个子数组中剩余的元素复制到原数组中。
-
在递归排序时,需要确定分解数组的位置,通常可以使用左右指针的方式来实现。
归并排序的时间复杂度为O(nlogn),它具有稳定性和适用于大规模数据排序的优点。但是,它需要额外的空间来存储临时数组,因此在实际应用中需要考虑内存的消耗。
Java 中List集合中自定义排序
/* 集合框架的工具类。 Collections:集合框架的工具类。里面定义的都是静态方法。 Collections和Collection有什么区别? Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。 它有两个常用的子接口, List:对元素都有定义索引。有序的。可以重复元素。 Set:不可以重复元素。无序。 Collections是集合框架中的一个工具类。该类中的方法都是静态的 提供的方法中有可以对list集合进行排序,二分查找等方法。 通常常用的集合都是线程不安全的。因为要提高效率。 如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。 */ import java.util.*; class Test3 public static void main(String[] args) System.out.println("-------------sortDemo---------------"); sortDemo(); System.out.println("-------------maxDemo---------------"); maxDemo(); /** * -------------sortDemo--------------- * [z, qq, zz, aaa, abcd, kkkkk] * -------------maxDemo--------------- * [aaa, abcd, kkkkk, qq, z, zz] * max=zz */ public static void sortDemo() List<String> list = new ArrayList<String>(); list.add("abcd"); list.add("aaa"); list.add("zz"); list.add("kkkkk"); list.add("qq"); list.add("z"); Collections.sort(list, new StrLenComparator()); sop(list); public static void maxDemo() List<String> list = new ArrayList<String>(); list.add("abcd"); list.add("aaa"); list.add("zz"); list.add("kkkkk"); list.add("qq"); list.add("z"); Collections.sort(list); sop(list); String max = Collections.max(list); sop("max=" + max); public static void sop(Object obj) System.out.println(obj); /** * 比较器,先按字符长度然后按自然排序 */ class StrLenComparator implements Comparator<String> public int compare(String s1, String s2) if (s1.length() > s2.length()) return 1; if (s1.length() < s2.length()) return -1; return s1.compareTo(s2);
以上是关于java中常用排序工具类, 使用的算法是什么?什么,怎么还有组合模式参与?的主要内容,如果未能解决你的问题,请参考以下文章