快速排序

本文深入解析了快速排序的实现原理,包括中值项选取、数据分区和递归过程,对比了快速排序与归并排序的不同,并提供了详细的代码示例,帮助读者理解和掌握快速排序算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现原理:

1、找出中值项M

2、将数据通过中值项分为 D1(所有小于等于M的数据) D2(所有大于M的数据)

3、在D1 D2中递归执行1/2/3

PS:中值项的选取,如果直接选取最中间的数据,在某些时候会导致快速排序的性能下降到O(N^2),

所以为了容错,选取数据的第一个,最后一个,中间的数据,对三个进行排序,再进行上诉的 1 2 3(1的规则在此说明) 

快速排序和归并排序的区别:

     1、归并需要额外的内存空间开销,是快速的两倍

     2、快速排序是先利用枢纽对数组进行分组(基于大于和小于枢纽的上下两个数组),再递归

     3、归并排序先递归,再进行排序

分治法理解: 快速是先治后分 ,归并是先分后治

归并排序请看 https://blog.youkuaiyun.com/fighterGuy/article/details/82179004

/**

 * 快速排序 效率: 3千万: 1898 30万: 28

 * 大O O(N*logN) 最差可能达到 O(N^2)

 * @author ThinkPad

 *

 */

public class FastSort {

       private long[] longArr;

 

       private int nElme;

 

       public FastSort(int size) {

             longArr = new long[size];

             nElme = 0;

       }

 

       public void insert(long value) {

             longArr[nElme++] = value;

       }

 

       public void display() {

             for (int i = 0; i < nElme; i++) {

                    System.out.print(longArr[i] + "  ");

             }

             System.out.println("  ");

       }

 

       public void quickSort() {

             recQuickSort(0, nElme - 1);

       }

 

       public void recQuickSort(int left, int right) {

             int size = right - left + 1;

             // 快速排序对小于4个的数据不支持,所以需要用其他算法排序或者直接写代码进行三个数值交换

             // 经试验得知 9的时候,用插入排序效果较好,故采用

             // 也可以先采用快速排序,不处理少于4个的情况,排序后使用插入排序,插入排序对有序数组有很高的效率

             //if (right - left <= 0) {

             // 此处采用的是不对少于10个进行处理,先完成快速排序再插入排序,用目前的程序有问题,partitionIt方法中--会出错

             //     return;

             //}

             if (size < 10) {

                    insertSort(left, right);

             } else {

                    // 找出三值中数项

                    long pivot = medianOfThree(left, right);

                    // 中数项作为将数组进行大小区分的枢纽传入,返回值为枢纽真实位置(后续不参与排序)

                    int position = partitionIt(left, right, pivot);

                    recQuickSort(left, position - 1);

                    recQuickSort(position + 1, right);

             }

 

       }

 

       public int partitionIt(int left, int right, long pivot) {

             // 最左侧的值是求三值中数项的最小值,没有和枢纽比较的必要,所以是 ++leftPart

             int leftPart = left;

             // 最右侧的值是求三值中数项的最大值,且将枢纽放到了 right - 1(表示数组倒数第二个值)的位置上,所以rightPart = right - 1

             // 并且 比较的时候使用--rightPart(表示倒数第三个值)

             int rightPart = right - 1;

             while (true) {

                    while (longArr[++leftPart] < pivot)

                           ;

                    while (longArr[--rightPart] > pivot)

                           ;

                    if (leftPart >= rightPart) {

                           break;

                    } else {

                           swap(leftPart, rightPart);

                    }

             }

             // 此处需要将获取三值中数项时把中数放入right - 1的值放回leftPart的位置上,因为那个位置是其真实的位置

             swap(leftPart, right - 1);

             return leftPart;

       }

 

       //三值中数项,避免出现最差的O(N^2)的出现,从最右边找枢纽,可能会出现数据的数据都需要移动的情况,这是最差的

       public long medianOfThree(int left, int right) {

             int mid = (left + right) / 2;

             if (longArr[left] > longArr[right]) {

                    swap(left, right);

             }

             if (longArr[left] > longArr[mid]) {

                    swap(left, mid);

             }

             if (longArr[mid] > longArr[right]) {

                    swap(right, mid);

             }

             // 将mid的中值项放在right - 1位置上,在排序的时候不需要对中值项进行对比,当排序完成之后将mid放回就可以

             swap(mid, right - 1);

             return longArr[right - 1];

       }

 

       private void swap(int left, int right) {

             long temp = longArr[left];

             longArr[left] = longArr[right];

             longArr[right] = temp;

       }

 

       // 从left开始 left + 1和left开始比较, 一直到right 和right - 1进行比较

       public void insertSort(int left, int right) {

             int j;

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

                    long temp = longArr[i];

                    j = i;

                    while (j > left && longArr[j - 1] >= temp) {

                           longArr[j] = longArr[j - 1];

                           --j;

                    }

                    longArr[j] = temp;

             }

       }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值