排序之快速排序

快速排序

原理:

  1. 从待排序区间选择一个数,作为基准值(pivot);
  2. Partition:
    遍历整个待排序区间,将比基准值小的(可以包含相等的)放到基准值的左边,将比基准值大的 (可以包含相等的)放到基准值的右边。
  3. 采用分治思想,对左右两个小区间按照同样的方式处理,直到小区间的长度 == 1,代表已经有序,或者小区 间的长度 == 0,代表没有数据。

实现:
下面几种方法都要用到的代码

public static void swap(int[] array,int left,int right) {
        int tmp = array[left];
        array[left] = array[right];
        array[right] = tmp;
    }

1、horen:

public static int Partion(int[] array,int left,int right) {
        int begin = left;
        int end = right - 1;
        int key = array[end];
        while(begin < end) {
            //1、left从前往后找比基准值大的元素
            while (begin < end && array[begin] <= key) {
                begin++;
            }
            //2、right从后往前找比基准值
            while (begin < end && array[end] >= key) {
                end--;
            }
            if (begin < end) {
                swap(array, begin, end);
            }
        }
        if(begin != right-1) {
            swap(array, begin, right - 1);
        }
        return begin;
    }

b、挖坑法

public static int Partion2(int[] array,int left,int right) {
        int begin = left;
        int end = right - 1;
        int key = array[end];
        while(begin < end) {
            while(begin < end && array[begin] < key) {
                begin++;
            }
            swap(array,begin,end);
            while (begin < end && array[end] > key) {
                end--;
            }
            swap(array,begin,end);
        }
        return 0;
    }

c、前后索引法

public static int Partion3(int[] array,int left,int right) {
        int cur = left;
        int prev = cur - 1;
        int key = array[right - 1];

        while (cur < right) {
            if(array[cur] < key && ++prev != cur) {
                swap(array,cur,prev);
            }
            ++cur;
            if(++prev != right - 1) {
                swap(array,prev,right - 1);

            }
        }
        return prev;
    }

性能分析:
稳定性:不稳定
存在最优情况:如果每次获取到的基准值都能够将区间划分成左右两半部分如:二叉树平衡树时间复杂度为0(NlogN)。
存在最差情况:每次划分之后,数据都在基准值的一-侧(每次拿到的基准值刚好是区间中的极值)如:单支树时间发杂度为0(N^2)。
优化方案:
尽量避免最差情况出现,采用三数取中法对降低获取到极值的概率。
三数取中法: left mid right—>返回返回着三个数据中最中间一个平均时间复杂度: 0(NlogN)
没有让递归到区间只剩一个数据时退出,因为递归到一定程度,区间中的数据实际慢慢的变少

非递归方法:
数据量如果比较大,递归层数比较深—>递归深度到一定程度,可能会导致栈溢出,这时采用非递归方法这里需要借助栈来实现。
代码实现:

public static void quickSortNor(int[] array) {
        Stack<Integer> stack = new Stack<>();
        stack.push(array.length);
        stack.push(0);
        while(!stack.empty()) {
            int left = stack.pop();
            int right = stack.pop();
            if(right-left > 1) {
                int div = Partion(array,left,right);
                stack.push(right);
                stack.push(div+1);
                stack.push(div);
                stack.push(left);
            }
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>