快速排序和快速选择(quickSort and quickSelect)算法

排序算法:快速排序(quicksort)递归与非递归算法
TopK问题:快速选择(quickSelect)算法

import java.util.*;
import java.lang.*;


public class Demo {

    // 非递归 using stack
    public static void quickSortStack(int[] nums, int left, int right) {
        if (left >= right) return;

        Stack<Range> stack = new Stack<Range>();
        stack.push( new Range(left, right) );

        while( !stack.empty() ) {
            Range curRange = stack.pop();
            if (curRange.left < curRange.right) {
                int pivotIdx = partition(nums, curRange.left, curRange.right);
                stack.push( new Range(curRange.left, pivotIdx - 1) );
                stack.push( new Range(pivotIdx + 1, curRange.right) );
            }
        }
    }

    // recursion quickSort
    public static void quickSort(int[] nums, int left, int right) {
            if (left < right) {
                    int pIdx = partition(nums, left, right);
                    quickSort(nums, left, pIdx - 1);
                    quickSort(nums, pIdx + 1, right);
            } 
    }

    public static int partition(int[] nums, int left, int right) {
        // nums[left]~nums[retIdx - 1] <= nums[retIdx] <= nums[retIdx ~ right]
        if (left == right) return left;

        int pivot = nums[left]; // mark the leftmost value as the pivot. and store it.
        int lp = left, rp = right;
        while(lp < rp) {
            while(lp < rp && nums[rp] >= pivot)
                rp--;
            nums[lp] = nums[rp]; //move the smaller value to left Range.

            while(lp < rp && nums[lp] <= pivot)
                lp++;
            nums[rp] = nums[lp]; // move the bigger value to right Range.
        }
        nums[lp] = pivot;

        return lp;
    }

    public static void swap(int[] nums, int i, int j) {
            int tmp = nums[i];
            nums[i] = nums[j];
            nums[j] = tmp;
    }

    public static int partitionV2(int[] nums, int left, int right) {
        int l = left;
        int r = right + 1;
        int pivot = nums[left];
        while(true) {
            while( l < right && nums[++l] < pivot )
                if ( l == right ) break;
            while( r > left && nums[--r] >= pivot )
                if ( r == left ) break;

            if (l >= r)
                break;
            swap(nums, l, r);
        }
        swap(nums, left, r);
        return r;
    }

    //TopK问题
    public static int findKthLargest(int[] nums, int k) {
            return quickSelect(nums, k, 0, nums.length - 1);
    }

    //快速选择算法
    public static int quickSelect(int[] nums, int k, int left, int right) {
            if (left == right) return nums[left];
            int index = partition(nums, left, right);
            if ( index - left + 1 == k) {
                    return nums[index];
            }
            else if ( index - left + 1 > k ) {
                    return quickSelect(nums, k, left, index - 1);
            }
            else {
                    return quickSelect(nums, k - index + left - 1, index + 1, right);
            }
    }

    public static void showArrays(int[] nums, String str) {
        System.out.println("===" + str + "===");
        showArrays(nums);
    }
    public static void showArrays(int[] nums) {
        for (int i = 0; i < nums.length; i++)
            System.out.printf(nums[i] + " ");
        System.out.println();
    }
    public static void main(String[] args) {
        int[] nums = new int[] {1,3,2,3,4,2,7,5};
        // int[] nums = new int[]{3,2,3};
        showArrays(nums, "origin");
        //print i-th min nubmer.
        for (int i = 1; i <= nums.length; i++) {
            System.out.println( i + " " + findKthLargest(nums, i) );
        }
        quickSortStack(nums, 0, nums.length - 1);
        showArrays(nums, "quickSortStack");
    }
}

class Range {
    public int left;
    public int right;

    public Range(int left, int right) {
        this.left = left;
        this.right = right;
    }
}

转载于:https://www.cnblogs.com/johnleo/p/quicksort_and_quickselect.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值