快速排序

快速排序

逻辑

采用分治思想的排序

  1. 定基准——选定一个基准默(默认为列表的最后一个元素)
  2. 划分区——分成比基准大、小的两个集合
  3. 递归调用——递归排序,拼装结果
  4. 注意递归终止条件,当集合只有一个元素
    『递归 + 非原地排序』的实现虽然简单易懂,但是如此一来『快速排序』便不再是最快的通用排序算法了,因为递归调用过程中非原地排序需要生成新数组,空间复杂度颇高。list comprehension 大法虽然好写,但是用在『快速排序』算法上就不是那么可取了。
    在这里插入图片描述
    Two-way partitioning
    对于仅使用一个索引进行 partition 操作的快排对于随机分布数列的效果还是不错的,但若数组本身就已经有序或者相等的情况下,每次划分仅能确定一个元素的最终位置,故最坏情况下的时间复杂度变为 O(n^2)O(n​2​​ ). 那么有什么办法尽可能避免这种最坏情况吗?聪明的人类总是能找到更好地解决办法——使用两个索引分别向右向左进行 partition.

先来一张动图看看使用两个索引进行 partition 的过程。Two-way partitioning

python

def quick_sort(collection):
    """
    out-in-place - 非原地快排
    『递归 + 非原地排序』的实现虽然简单易懂,但是如此一来『快速排序』便不再是最快的通用排序算法了,因为递归调用过程中非原地排序需要生成新数组,空间复杂度颇高。
    :param collection:
    :return:
    """
    print(collection)
    length = len(collection)
    if length <= 1:
        return collection
    pivot = collection.pop()
    greater, lesser = [], []
    for num in collection:
        if num > pivot:
            greater.append(num)
        else:
            lesser.append(num)
    return quick_sort(lesser) + [pivot] +quick_sort(greater)
    
def quick_sort1(arr, low, upper):
	"""
	in-place - 原地快排
	one index for partition
	"""
    print(arr)
    if low >= upper:
        return
    m = low
    for i in range(low + 1, upper + 1):
        if arr[i] < arr[low]:
            m += 1
            arr[m], arr[i] = arr[i], arr[m]
    # 交换m和low的位置
    arr[m], arr[low] = arr[low], arr[m]
    print(arr)
    quick_sort1(arr, low, m - 1)
    quick_sort1(arr, m + 1, upper)

unsortedArray = [6, 5, 3, 1, 8, 7, 2, 4]
print(quick_sort1(unsortedArray, 0, len(unsortedArray) - 1))

def quick_sort2(arr, low, upper):
    '''
    Two-way partitioning
    '''
    print(arr)
    if low >= upper:
        return arr
    target = arr[low]
    left, right = low + 1, upper
    while left <= right:
        while left <= right and arr[left] < target:
            left += 1
        while left <= right and arr[left] > target:
            right -= 1
        if left > right:
            break
        arr[left], arr[right] = arr[right], arr[left]
    arr[low], arr[right] = arr[right], arr[low]
    quick_sort2(arr, low, right - 1)
    quick_sort2(arr, right + 1, upper)

java

public class quickSort {
    public static void main(String[] args) {
        int unsortedArray[] = new int[]{6, 5, 3, 1, 8, 7, 2, 4};
        quickSort(unsortedArray);
    }

    public static void quickSort1(int[] array,int l,int u) {
        for (int item : array) {
            System.out.print(item + "");
        }
        System.out.println();
        if (l>u) return;
        int m =l;
        for (int i = l+1;i<=u;i++){
            if (array[i]<array[l]){
                m +=1;
                int temp = array[m];
                array[m] = array[i];
                array[i] = temp;
            }
        }
        int temp = array[m];
        array[m] = array[l];
        array[l] = temp;
        quickSort1(array,l,m-1);
        quickSort1(array,m+1,u);
    }

    public static void quickSort2(int[] array, int l ,int u) {
        for (int item :array){
            System.out.print(item+"");
        }
        System.out.println();
        if (l >= u) return;
        int pivot = array[l];
        int left = l + 1;
        int right = u;
        while (left <= right) {
            while (left <= right && array[left] < pivot) {
                left++;
            }
            while (left <= right && array[right] >= pivot) {
                right--;
            }
            if (left > right) break;
            int temp = array[left];
            array[left] = array[right];
            array[right] = temp;
        }
        int temp = array[right];
        array[right] = array[l];
        array[l] = temp;

        quickSort2(array, l, right - 1);
        quickSort2(array, right + 1, u);
    }

    public static void quickSort(int[] array) {
        quickSort2(array,0,array.length-1);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值