快速排序的非递归实现(利用栈)

快速排序

  1. 递归算法使用的栈由程序自动产生,栈中包含:函数调用时的参数和函数中的局部变量。如果局部变量很多或者函数内部又调用了其他函数,则栈会很大。每次递归调用都要操作很大的栈,效率自然会下降。
  2. 非递归算法程序员手动利用栈来存储每次分块快排的起始点,栈非空时循环获取中轴入栈。
package sort;

import java.util.Objects;
import java.util.Stack;

/**
 * 快速排序的原理:

 选择一个关键值作为基准值。比基准值小的都在左边序列(一般是无序的),比基准值大的都在右边(一般是无序的)。一般选择序列的第一个元素。

 一次循环:从后往前比较,用基准值和最后一个值比较,如果比基准值小的交换位置,如果没有继续比较下一个,直到找到第一个比基准值小的值才交换。

 找到这个值之后,又从前往后开始比较,如果有比基准值大的,交换位置,如果没有继续比较下一个,直到找到第一个比基准值大的值才交换。

 直到从前往后的比较索引>从后往前比较的索引,结束第一次循环,此时,对于基准值来说,左右两边就是有序的了。

 接着分别比较左右两边的序列,重复上述的循环。


 */
public class FastSort{

    public static void main(String []args){
        int[] a = {12,20,5,16,15,1,30,45,23,9};
        int start = 0;
        int end = a.length-1;
//        sort(a,start,end);
        //非递归 栈实现
        quickSort(a);
        for(int i = 0; i<a.length; i++){
            System.out.println(a[i]);
        }

    }

//    public static void sort(int[] a,int low,int high){
//        int start = low;
//        int end = high;
//        //第一个数字key为基准值
//        int key = a[low];
//
//        while(end>start){
//            //从后往前end--,比较a[end]小于key,交换a[end]和key
//            while(end>start&&a[end]>=key)  //如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
//                end--;
//            if(a[end]<=key){
//                int temp = a[end];
//                a[end] = a[start];
//                a[start] = temp;
//            }
//            //从前往后比较
//            while(end>start&&a[start]<=key)//如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
//                start++;
//            if(a[start]>=key){
//                int temp = a[start];
//                a[start] = a[end];
//                a[end] = temp;
//            }
//            //此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
//        }
//        //递归
//        if(start>low) sort(a,low,start-1);//左边序列。第一个索引位置到关键值索引-1
//        if(end<high) sort(a,end+1,high);//右边序列。从关键值索引+1到最后一个
//    }

    private static void quickSort(int[] array) {
        if (array == null || array.length == 1) {
            return;
        }
        //存放开始于结束索引
        Stack<Integer> stack = new Stack<>();
        stack.push(0);
        stack.push(array.length - 1);
        //循环读取栈中的开始结束位置
        while (!stack.isEmpty()) {
            int right = stack.pop();
            int left = stack.pop();
            //右边界索引小于左边界索引说明结束了
            if (left >= right) {
                continue;
            }
            int i = partition(array, left, right);
            if (left < i - 1) {
                stack.push(left);
                stack.push(i -  1);
            }
            if (i + 1 < right) {
                stack.push(i + 1);
                stack.push(right);
            }
        }
    }

    public static int partition(int[] array, int left, int right) {

        int threshold = array[left];

        while (left < right) {
            while (left < right && array[right] >= threshold) {
                right--;
            }

            array[left] = array[right];

            while (left < right && array[left] <= threshold) {
                left++;
            }
            array[right] = array[left];

        }
        array[left] = threshold;
        return left;

    }


}

 

转载:https://blog.csdn.net/owenchan1987/article/details/50740479

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值