35-咸鱼学Java-快速排序的几种优化方式

快速排序介绍
在此文章之前请先阅读快速排序
快速排序的优化主要是再基准的选择上和尽量减少partition的运行。
其基准选择有几种方法1.随机选择法2.三分取中法,等等。
减少partition的方法主要输相同元素聚合。
其实现方法为

1.随机选择法

原来的选择基准为一直选择low下标的元素,所以在处理某些大量有序的序列的时候就会造成大量的元素在一侧,使得快排没有任何效果。
此时只需要在快排前面加入一段代码。

//产生start - end 的随机数
int randomNum=  (int)(Math.random()*(end-start)+start);
//交换start下标和随机位置的两个数,因为我们的partition默认取的是
//start位置所以可以通过换位置实现以随机位置为基准。
swap(array, start,randomNum);

2.三分取中法

加入一个函数

    /**
     * 三分取中
     * @param array 数组
     * @param low   下限
     * @param hight 上限
     */
    public static void  SelectThreeMid(int[] array,int low,int hight)
    {
        int mid = (low+hight)>>>1;
        if(array[low]<array[mid])   //目标low>mid
        {
            swap(array, mid, low);
        }
        if(array[hight]<array[mid]) //目标hight>mid
        {
            swap(array, hight, mid);
        }
        if(array[low]>array[hight]) //目标low<hight
        {
            swap(array, low, hight);
        }
        //最终结果为 low 下标的为中间值
    }

只需要将这行代码插入到partition执行之前,此代码就会将三个数中中间的数放入到下限下标,然后partition就会用下限下标来作为标准快排。

3.同元素聚合法

同元素聚合及为当以某个元素当做partition的基准的时候,顺便将和其相同的元素聚合在一起然后再进行partition。
函数

    /**
     * 聚集和基准相同的元素
     * @param array 数组
     * @param start 开始下标
     * @param end   结束下标
     * @param par   基准
     */
    private static int[] focus(int[] array, int start, int end, int par) {
        //查找的范围
        int left = par-1;
        int right = par+1;
        //交换的指引变量
        int parLeft = par-1;
        int parRight = par+1;
        //左边找相同的
        for (int i = left; i >=start; i--) {
            //当找到相同的
            if(array[i] == array[par])
            {
                //如果不相邻
                if(i!=parLeft)
                {   //i和交换的指引下标进行交换
                    swap(array, parLeft, i);
                    //指引下标移动
                    parLeft--;
                }
                else
                {   //如果相邻,只移动指引下标
                    parLeft--;
                }

            }

        }
        //右边找 原理同上
        for (int i = right; i <=end; i++) {
            if(array[i] == array[par])
            {
                if(i!=parRight)
                {
                    swap(array, parRight, i);
                    parRight++;
                }
                else
                {
                    parRight++;
                }
            }
        }
        //new一个数组,放入聚合在一起元素的上下限,及下次快排应该越过其,只在其上下限进行排序
        int [] focus = {parLeft,parRight};
        return focus;
    }

这个要对快速排序的函数进行改造

public static void Quick(int[] array,int start,int end)
    {   
        //先找到基准下标
        int par = partion(array, start, end);
        //调用聚集函数,聚集,找到应该快排的区段
        int[] focus = focus(array,start,end,par);
        int left = focus[0];
        int right = focus[1];
        //判断基准的左边是不是还有1个以上元素,如果是再调用快排
        if(par>start+1)
        {    
            Quick(array, start, left);
        }
        //判断基准的右边是不是还有1个以上元素,如果是再调用快排
        if(par<end-1)
        {   
            Quick(array, right, end);
        }
    }

4.当数据量小到某个节点的使用使用快排

快排函数

/**
     * 给某个区段快速排序 [start,end]
     * @param array
     * @param start
     * @param end
     */
    private static void insert_sort(int[] array,int start,int end) {
        int temp = 0;
        int j = 0;
        for (int i = start+1; i < end+1; i++) {
            temp = array[i];
            for (j = i-1; j >= 0 ; j--) {
                if(array[j]>temp){
                array[j+1] = array[j];
                }else
                {
                    break;
                }
            }
            array[j+1] = temp;
        }
    }

快排函数改造
在快排函数的第一行加上

    if(end-start+1<num)
    {
        insert_sort(array,start,end);
        return;
    }

此函数可以实现在快排的数量级小于num的时候实现插入排序。

最佳方案

以上方案有的可以叠加使用,当然效果是最好的
查阅资料可知,以上方法的组合,目前最快的可能是三数取中+聚集+插入排序

### 咸鱼平台上的快速排序算法模板 在咸鱼平台上查找与快速排序相关的模板或实现方法时,可以通过关键词搜索或者浏览相关商品描述中的代码示例。以下是基于已有引用内容整理的一个通用的快速排序算法模板[^1]: #### 快速排序的核心逻辑 快速排序是一种分治策略的应用,其核心思想是选取一个基准数(pivot),并通过一次遍历将数组分为两部分:一部分小于等于基准数,另一部分大于基准数。随后递归地对这两部分继续执行相同的操作。 ```javascript const quickSort = (arr, left = 0, right = arr.length - 1) => { if (left < right) { // 如果左指针小于右指针,则继续划分 let pos = partition(arr, left, right); quickSort(arr, left, pos - 1); // 对左侧子数组进行快速排序 quickSort(arr, pos + 1, right); // 对右侧子数组进行快速排序 } return arr; }; // 划分函数 function partition(arr, left, right) { let pivotIndex = right; // 将最右侧元素设为基准值 let pivotValue = arr[pivotIndex]; let index = left; for (let i = left; i < right; i++) { if (arr[i] < pivotValue) { // 若当前元素小于基准值 swap(arr, i, index); // 交换到左侧区域 index++; } } swap(arr, index, pivotIndex); // 将基准值放到中间位置 return index; } // 辅助函数:用于交换两个索引处的值 function swap(arr, i, j) { [arr[i], arr[j]] = [arr[j], arr[i]]; } ``` 上述代码是一个标准的 JavaScript 版本的快速排序实现[^3],适用于大多数场景下的需求。如果需要更高效的版本,可以根据具体应用场景优化基准值的选择方式以及分区操作。 --- ### 如何在咸鱼上找到类似的模板? 1. **关键词搜索** 使用“快速排序”、“JavaScript 排序算法”等关键词在咸鱼平台上进行搜索,可能会发现一些开发者分享的习资料或源码包。 2. **筛选条件** 结合价格区间、评价数量等因素挑选可信度较高的卖家资源。注意查看买家评论区是否有实际运行效果展示。 3. **联系卖家确认细节** 购买前可向卖家咨询具体的实现语言和支持的功能范围,比如是否支持自定义比较器等功能扩展。 --- ### 注意事项 虽然现代编程环境中许多高级语言已经内置了高效稳定的排序功能(如 C 的 `qsort` 函数[^2] 或 Python 的 `sorted()` 方法),但在习阶段亲手实践经典算法仍然非常重要。这不仅有助于理解底层原理,还能提升解决问题的能力。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值