前提:在可运行的SpringBoot的项目内引用以下JAR包
整个工具的代码都在Gitee或者Github地址内
Gitee: gitee.com/steven_Huan…
Github: github.com/ZeroNing/so…
1. 新增排序枚举
public enum SortTypeEnum {
BUCKET_SORT("桶排序",new BucketSortService()),
MERGE_SORT("归并排序",new MergeSortService()),
SHELL_SORT("希尔排序",new ShellSortService()),
HEAP_SORT("堆排序",new HeapSortService()),
QUICK_SORT("快速排序",new QuickSortService()),
INSERTION_SORT("插入排序",new InsertionSortService()),
SELECTION_SORT("选择排序",new SelectionSortService()),
BUBBLE_SORT("冒泡排序",new BubbleSortService()),
COMB_SORT("梳排序",new CombSortService()),
LIBRARY("图书馆排序",new LibrarySortService()),
GNOME("地精排序",new GnomeSortService()),
BITON("双调排序",new BitonicSortService()),
CYCLE("圈排序",new CycleSortService()),
COCKTAIL("鸡尾酒排序",new CocktailSortService()),
;
private String desc;
private SortService service;
SortTypeEnum(String desc, SortService service) {
this.desc = desc;
this.service = service;
}
public SortService getService() {
return service;
}
public String getDesc() {
return desc;
}
}
2. 冒泡排序实现
/**
* 冒泡排序
*/
public class BubbleSortService implements SortService {
@Override
public <T> Collection<T> sort(Collection<T> list, Comparator<? super T> comparator) {
List<T> sortedList = new ArrayList<>(list); // 创建一个副本以避免修改原始列表
boolean swapped;
int n = sortedList.size();
do {
swapped = false;
for (int i = 1; i < n; i++) {
// 使用比较器比较相邻元素
if (comparator.compare(sortedList.get(i - 1), sortedList.get(i)) > 0) {
// 如果前一个元素大于后一个元素,则交换它们
Collections.swap(sortedList, i - 1, i);
swapped = true;
}
}
// 减少下一次遍历的范围,因为每轮遍历都会将最大的元素移动到正确的位置
n--;
} while (swapped); // 如果某轮遍历没有发生交换,说明列表已经排序完成
return sortedList; // 返回排序后的列表
}
}
3. 桶排序实现
/**
* 桶排序
*/
public class BucketSortService implements SortService {
@Override
public <T> Collection<T> sort(Collection<T> list,Comparator<? super T> comparator) {
// 找到列表中的最大值和最小值
T min = Collections.min(list, comparator);
T max = Collections.max(list, comparator);
if (comparator.compare(max, min) == 0) {
return new ArrayList<>(list); // 如果min和max相等,所有元素都相同,直接返回
}
// 计算桶的数量
int bucketCount = Math.max(1, (int) Math.sqrt(list.size())); // 使用列表大小的平方根作为桶的数量
List<List<T>> buckets = new ArrayList<>(bucketCount);
for (int i = 0; i < bucketCount; i++) {
buckets.add(new ArrayList<>());
}
// 将元素分配到各个桶中
long divisor = comparator.compare(max, min);
for (T element : list) {
int bucketIndex = (int) ((long) comparator.compare(element, min) * (bucketCount - 1) / divisor);
buckets.get(bucketIndex).add(element);
}
// 对每个桶内的元素进行排序
for (List<T> bucket : buckets) {
bucket.sort(comparator);
}
// 合并所有桶中的元素
List<T> sortedList = new ArrayList<>(list.size());
for (List<T> bucket : buckets) {
sortedList.addAll(bucket);
}
return sortedList;
}
}
4. 堆排序实现
/**
* 堆排序
*/
public class HeapSortService implements SortService {
@Override
public <T> Collection<T> sort(Collection<T> list, Comparator<? super T> comparator) {
int n = list.size();
List<T> data = new ArrayList<>(list);
// 构建最大堆
for (int i = n / 2 - 1; i >= 0; i--) {
heapify(data, i, n, comparator);
}
// 一个一个地从堆中取出元素
for (int i = n - 1; i >= 0; i--) {
swap(data, 0, i);
// 重新对堆进行调整
heapify(data, 0, i, comparator);
}
return data;
}
private static <T> void heapify(List<T> list, int i, int n, Comparator<? super T> comparator) {
int largest = i; // 初始化最大值为根节点
int left = 2 * i + 1; // 左子节点
int right = 2 * i + 2; // 右子节点
// 如果左子节点在范围内且大于根节点
if (left < n && comparator.compare(list.get(left), list.get(largest)) > 0) {
largest = left;
}
// 如果右子节点在范围内且大于当前最大值
if (right < n && comparator.compare(list.get(right), list.get(largest)) > 0) {
largest = right;
}
// 如果最大值不是根节点
if (largest != i) {
swap(list, i, largest);
// 递归地调整受影响的子树
heapify(list, largest, n, comparator);
}
}
private static <T> void swap(List<T> list, int i, int j) {
T temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
5. 插入排序实现
/**
* 插入排序
*/
public class InsertionSortService implements SortService {
@Override
public <T> Collection<T> sort(Collection<T> list, Comparator<? super T> comparator) {
List<T> sortedList = new ArrayList<>(list); // 创建一个副本以避免修改原始列表
int n = sortedList.size();
for (int i = 1; i < n; i++) {
T key = sortedList.get(i);
int j = i - 1;
// 将比 key 大的元素都向右移动
while (j >= 0 && comparator.compare(sortedList.get(j), key) > 0) {
sortedList.set(j + 1, sortedList.get(j));
j--;
}
// 插入 key 到正确的位置
sortedList.set(j + 1, key);
}
return sortedList; // 返回排序后的列表
}
}
6. 归并排序实现
/**
* 归并排序
*/
public class MergeSortService implements SortService {
@Override
public <T> Collection<T> sort(Collection<T> list, Comparator<? super T> comparator) {
if (list.size() <= 1) {
return list;
}
List<T> data = new ArrayList<>(list);
// 分割列表
int middle = list.size() / 2;
Collection<T> left = new ArrayList<>(data.subList(0, middle));
Collection<T> right = new ArrayList<>(data.subList(middle, list.size()));
// 递归排序左右两部分
left = sort(left, comparator);
right = sort(right, comparator);
// 合并排序后的左右两部分
return merge((List<T>) left, (List<T>) right, comparator);
}
private static <T> Collection<T> merge(List<T> left, List<T> right, Comparator<? super T> comparator) {
List<T> result = new ArrayList<>();
int leftIndex = 0;
int rightIndex = 0;
// 合并两个有序列表
while (leftIndex < left.size() && rightIndex < right.size()) {
if (comparator.compare(left.get(leftIndex), right.get(rightIndex)) <= 0) {
result.add(left.get(leftIndex));
leftIndex++;
} else {
result.add(right.get(rightIndex));
rightIndex++;
}
}
// 添加剩余的元素
while (leftIndex < left.size()) {
result.add(left.get(leftIndex));
leftIndex++;
}
while (rightIndex < right.size()) {
result.add(right.get(rightIndex));
rightIndex++;
}
return result;
}
private static <T> Collection<T> merge(List<T> left, List<T> right, Comparator<? super T> comparator, boolean ascending) {
List<T> result = new ArrayList<>();
int leftIndex = 0;
int rightIndex = 0;
// 合并两个有序列表
while (leftIndex < left.size() && rightIndex < right.size()) {
int comparison = comparator.compare(left.get(leftIndex), right.get(rightIndex));
if (ascending ? comparison <= 0 : comparison >= 0) {
result.add(left.get(leftIndex));
leftIndex++;
} else {
result.add(right.get(rightIndex));
rightIndex++;
}
}
// 添加剩余的元素
while (leftIndex < left.size()) {
result.add(left.get(leftIndex));
leftIndex++;
}
while (rightIndex < right.size()) {
result.add(right.get(rightIndex));
rightIndex++;
}
return result;
}
}
7. 快速排序实现
/**
* 快速排序
*/
public class QuickSortService implements SortService {
@Override
public <T> Collection<T> sort(Collection<T> list, Comparator<? super T> comparator) {
List<T> sortedList = new ArrayList<>(list); // 创建一个副本以避免修改原始列表
quickSort(sortedList, comparator);
return sortedList; // 返回排序后的列表
}
private static <T> void quickSort(List<T> list, Comparator<? super T> comparator) {
Stack<int[]> stack = new Stack<>();
stack.push(new int[]{0, list.size() - 1});
while (!stack.isEmpty()) {
int[] range = stack.pop();
int low = range[0];
int high = range[1];
if (low < high) {
int pivotIndex = partition(list, low, high, comparator);
stack.push(new int[]{low, pivotIndex - 1});
stack.push(new int[]{pivotIndex + 1, high});
}
}
}
private static <T> int partition(List<T> list, int low, int high, Comparator<? super T> comparator) {
T pivot = list.get(high); // 选择高位为基准
int i = low - 1; // 指定小于基准的区域
for (int j = low; j < high; j++) {
if (comparator.compare(list.get(j), pivot) <= 0) {
i++;
swap(list, i, j);
}
}
swap(list, i + 1, high); // 将基准元素放置在正确位置
return i + 1;
}
private static <T> void swap(List<T> list, int i, int j) {
T temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
private static <T> void quickSortHelper(List<T> list, int low, int high, Comparator<? super T> comparator) {
if (low < high) {
int pivotIndex = partition(list, low, high, comparator);
quickSortHelper(list, low, pivotIndex - 1, comparator);
quickSortHelper(list, pivotIndex + 1, high, comparator);
}
}
}
8. 选择排序实现
/**
* 选择排序
*/
public class SelectionSortService implements SortService {
@Override
public <T> Collection<T> sort(Collection<T> list, Comparator<? super T> comparator) {
List<T> sortedList = new ArrayList<>(list); // 创建一个副本以避免修改原始列表
int n = sortedList.size();
for (int i = 0; i < n - 1; i++) {
int selectedIndex = i;
for (int j = i + 1; j < n; j++) {
// 使用复合比较器比较元素
if (comparator.compare(sortedList.get(j), sortedList.get(selectedIndex)) < 0) {
selectedIndex = j; // 找到更小(或更大)的元素索引
}
}
// 交换 selectedIndex 和 i 位置上的元素
if (selectedIndex != i) {
T temp = sortedList.get(selectedIndex);
sortedList.set(selectedIndex, sortedList.get(i));
sortedList.set(i, temp);
}
}
return sortedList; // 返回排序后的列表
}
}
9. 希尔排序实现
/**
* 希尔排序
*/
public class ShellSortService implements SortService {
@Override
public <T> Collection<T> sort(Collection<T> list, Comparator<? super T> comparator) {
// 创建列表的副本,以避免修改原始列表
List<T> sortedList = new ArrayList<>(list);
// 初始化间隔gap为列表大小的一半
int gap = sortedList.size() / 2;
// 逐步减小间隔,直到gap为0
while (gap > 0) {
// 从gap位置开始遍历列表
for (int i = gap; i < sortedList.size(); i++) {
T temp = sortedList.get(i);
int j = i;
// 使用复合比较器进行比较
while (j >= gap && comparator.compare(sortedList.get(j - gap), temp) > 0) {
sortedList.set(j, sortedList.get(j - gap));
j -= gap;
}
sortedList.set(j, temp);
}
// 缩小间隔
gap /= 2;
}
// 返回排序后的列表
return sortedList;
}
}
10.梳排序
/**
* 梳排序
*/
public class CombSortService implements SortService {
@Override
public <T> Collection<T> sort(Collection<T> list, Comparator<? super T> comparator) {
// 将提供的集合转换为ArrayList,以便进行更简单的计算
ArrayList<T> arrayList = new ArrayList<>(list);
// 初始化梳排序的收缩因子和间隔
double shrinkFactor = 1.3;
int gap = arrayList.size();
// 初始化swapped为false。它用于检查我们是否需要继续排序过程
boolean swapped = false;
// 当间隔大于1或者最后一次排序已经发生过交换时,继续排序
while (gap > 1 || swapped) {
// 如果间隔大于1,就将其除以收缩因子
if (gap > 1) {
gap = (int) (gap / shrinkFactor);
}
// 将swapped设置为false
swapped = false;
// 遍历列表,并比较当前元素和间隔后的元素
for (int i = 0; gap + i < arrayList.size(); i++) {
// 如果当前元素大于间隔后的元素,就交换它们
if (comparator.compare(arrayList.get(i), arrayList.get(i + gap)) > 0) {
Collections.swap(arrayList, i, i + gap);
// 如果发生了交换,就将swapped设置为true
swapped = true;
}
}
}
// 返回排序后的列表
return arrayList;
}
}
11.图书馆排序
/**
* 图书馆排序
*/
public class LibrarySortService implements SortService {
@Override
public <T> Collection<T> sort(Collection<T> list, Comparator<? super T> comparator) {
// 将输入集合转换为列表,以便进行索引操作
List<T> sortedList = new ArrayList<>(list);
// 初始化间隔
int n = sortedList.size();
int gap = (int) Math.sqrt(n);
// 使用间隔进行插入排序
for (int i = gap; i < n; i++) {
T key = sortedList.get(i);
int j = i;
// 将元素插入到已排序序列中的正确位置
while (j >= gap && comparator.compare(sortedList.get(j - gap), key) > 0) {
sortedList.set(j, sortedList.get(j - gap));
j -= gap;
}
sortedList.set(j, key);
}
// 最后进行一次标准的插入排序,以确保所有元素都已正确排序
for (int i = 1; i < n; i++) {
T key = sortedList.get(i);
int j = i - 1;
while (j >= 0 && comparator.compare(sortedList.get(j), key) > 0) {
sortedList.set(j + 1, sortedList.get(j));
j--;
}
sortedList.set(j + 1, key);
}
return sortedList;
}
}
12.地精排序
/**
* 地精排序
*/
public class GnomeSortService implements SortService {
@Override
public <T> Collection<T> sort(Collection<T> list, Comparator<? super T> comparator) {
// 将输入集合转换为列表,以便进行索引操作
List<T> sortedList = new ArrayList<>(list);
int index = 0;
int n = sortedList.size();
while (index < n) {
if (index == 0 || comparator.compare(sortedList.get(index), sortedList.get(index - 1)) >= 0) {
index++;
} else {
// 交换当前元素和前一个元素
T temp = sortedList.get(index);
sortedList.set(index, sortedList.get(index - 1));
sortedList.set(index - 1, temp);
index--;
}
}
return sortedList;
}
}
13.双调排序
/**
* 双调排序
*/
public class BitonicSortService implements SortService {
@Override
public <T> Collection<T> sort(Collection<T> list, Comparator<? super T> comparator) {
// 将输入集合转换为列表,以便进行索引操作
List<T> sortedList = new ArrayList<>(list);
int n = sortedList.size();
// 调整为2的幂,因为双调排序要求元素数量必须是2的幂
// 如果不是,需要填充到2的幂,这里为了简单起见,我们假设n已经是2的幂
assert (n & (n - 1)) == 0 : "The number of elements must be a power of 2";
// 开始双调排序过程
bitonicSort(sortedList, 0, n, true, comparator);
return sortedList;
}
// 递归实现双调序列的创建和比较
private <T> void bitonicSort(List<T> list, int low, int count, boolean ascending, Comparator<? super T> comparator) {
if (count > 1) {
int k = count / 2;
// 创建升序双调序列
bitonicSort(list, low, k, true, comparator);
// 创建降序双调序列
bitonicSort(list, low + k, k, false, comparator);
// 合并双调序列
bitonicMerge(list, low, count, ascending, comparator);
}
}
// 合并双调序列
private <T> void bitonicMerge(List<T> list, int low, int count, boolean ascending, Comparator<? super T> comparator) {
if (count > 1) {
int k = greatestPowerOfTwoLessThan(count);
for (int i = low; i < low + count - k; i++) {
if (ascending == (comparator.compare(list.get(i), list.get(i + k)) > 0)) {
// 交换元素
T temp = list.get(i);
list.set(i, list.get(i + k));
list.set(i + k, temp);
}
}
bitonicMerge(list, low, k, ascending, comparator);
bitonicMerge(list, low + k, count - k, ascending, comparator);
}
}
// 找到小于当前count的最大2的幂
private int greatestPowerOfTwoLessThan(int count) {
int k = 1;
while (k < count) {
k = k << 1;
}
return k >> 1;
}
}
14.圈排序
/**
* 圈排序
*/
public class CycleSortService implements SortService {
@Override
public <T> Collection<T> sort(Collection<T> list, Comparator<? super T> comparator) {
// 将输入集合转换为列表,以便进行索引操作
List<T> sortedList = new ArrayList<>(list);
int n = sortedList.size();
// 开始圈排序过程
for (int cycleStart = 0; cycleStart < n - 1; cycleStart++) {
T item = sortedList.get(cycleStart);
// 找到item的正确位置
int pos = cycleStart;
for (int i = cycleStart + 1; i < n; i++) {
if (comparator.compare(sortedList.get(i), item) < 0) {
pos++;
}
}
// 如果item已经在正确位置,继续下一个循环
if (pos == cycleStart) {
continue;
}
// 跳过重复元素
while (comparator.compare(item, sortedList.get(pos)) == 0) {
pos++;
}
// 将item放到正确位置,并将正确位置的元素保存到item
if (pos != cycleStart) {
T temp = item;
item = sortedList.get(pos);
sortedList.set(pos, temp);
}
// 旋转剩余的圈
while (pos != cycleStart) {
pos = cycleStart;
// 找到item的正确位置
for (int i = cycleStart + 1; i < n; i++) {
if (comparator.compare(sortedList.get(i), item) < 0) {
pos++;
}
}
// 跳过重复元素
while (comparator.compare(item, sortedList.get(pos)) == 0) {
pos++;
}
// 将item放到正确位置,并将正确位置的元素保存到item
if (comparator.compare(item, sortedList.get(pos)) != 0) {
T temp = item;
item = sortedList.get(pos);
sortedList.set(pos, temp);
}
}
}
return sortedList;
}
}
15.鸡尾酒排序
/**
* 鸡尾酒排序
*/
public class CocktailSortService implements SortService {
@Override
public <T> Collection<T> sort(Collection<T> list, Comparator<? super T> comparator) {
List<T> dataList = new ArrayList<>(list); // 将Collection转换为List,因为List支持通过索引访问
boolean swapped;
int start = 0;
int end = dataList.size() - 1;
do {
swapped = false;
// 正向遍历,找到最大元素
for (int i = start; i < end; ++i) {
if (comparator.compare(dataList.get(i), dataList.get(i + 1)) > 0) {
T temp = dataList.get(i);
dataList.set(i, dataList.get(i + 1));
dataList.set(i + 1, temp);
swapped = true;
}
}
if (!swapped) {
break;
}
swapped = false;
end--;
// 反向遍历,找到最小元素
for (int i = end - 1; i >= start; --i) {
if (comparator.compare(dataList.get(i), dataList.get(i + 1)) > 0) {
T temp = dataList.get(i);
dataList.set(i, dataList.get(i + 1));
dataList.set(i + 1, temp);
swapped = true;
}
}
start++;
} while (swapped);
return dataList;
}
}
16. 排序接口
public interface SortService {
/**
* 对给定的列表进行排序
*
* @param <T> 列表元素的类型
* @param list 要排序的列表
* @param comparator 用于比较列表元素的比较器
* @return 排序后的列表
*/
<T> Collection<T> sort(Collection<T> list, Comparator<? super T> comparator);
}
17. 排序工具
public class SortUtil {
/**
* 对给定的列表进行排序,支持升序和降序排序。
*
* @param <T> 列表元素的类型
* @param sortTypeEnum 排序类型
* @param list 要排序的列表
* @param comparator 用于比较列表元素的比较器
* @return 排序后的列表
*/
public static <T> Collection<T> sort(SortTypeEnum sortTypeEnum, Collection<T> list, Comparator<? super T> comparator) {
if (ValidateUtils.isEmpty(list)) {
return list;
}
return sortTypeEnum.getService().sort(list, comparator);
}
}
18. 测试方法
public static void main(String[] args) {
List<Person> b = new ArrayList<>();
for (Integer i = 0; i < 10000000; i++) {
b.add(new Person(String.valueOf(i * 15),i*13));
}
System.out.println("============多字段排序算法降序开始=======================\n");
System.out.println("总记录数:" + b.size() + "排序测试\n");
for(SortTypeEnum typeEnum : SortTypeEnum.values()){
StopWatch stopWatch = new StopWatch();
stopWatch.start();
SortUtil.sort(typeEnum,b, Comparator.comparing(Person::getAge).thenComparing(Person::getName).reversed());
stopWatch.stop();
System.out.println(typeEnum.getDesc() + "算法:降序耗时:" + stopWatch.getTotalTimeSeconds() + "秒");
System.out.print("\n");
}
}
static class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
19. 测试结果
============排序算法降序开始=======================
总记录数:1000000排序测试
冒泡排序算法:降序耗时:13582秒
桶排序算法: 降序耗时:0秒
堆排序算法: 降序耗时:1秒
插入排序算法:降序耗时:14144秒
归并排序算法:降序耗时:0秒
快速排序算法:降序耗时:2秒
选择排序算法:降序耗时:13388秒
希尔排序算法:降序耗时:1秒