java整合通用排序方法(桶排序,归并排序,希尔排序,堆排序,快速排序,插入排序,选择排序,冒泡排序,梳排序,图书馆排序,地精排序,双调排序,圈排序,鸡尾酒排序

40 阅读6分钟

前提:在可运行的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秒