快速排序Partition的写法

本文详细介绍了快速排序算法中Partition的五种不同实现方式,包括从头前进法、首尾夹逼法等,每种方法都有其独特之处,通过随机选取基准值并调整数组元素,达到划分数组的效果,从而提升排序效率。

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

快速排序的重点在于Partition的写法,Partition主要有两种写法:从头前进法,首尾夹逼法。

Partition写法一

首先需要做出求解问题的区间,为此,指定 pivot = nums[left],并定义两个变量 i, j

  • [left+1, j] 区间所在元素都小于pivot

  • (j, i]区间所在元素都大于pivot

初始化 i 和 j 都是left,可以写出如下代码:

int partition(int *nums, int left, int right)
{
    int randomIndex = left + random(right - left + 1); // 初始化为数组的随机位置
    swap(nums, left, randomIndex);
    
    int pivot = nums[left];
    int i = left + 1, j = left;
    while (i <= right) {
        if (nums[i] <= pivot) {
            swap(nums, i, ++j);
        }
        
        i++;
    }
    
    swap(nums, left, j);
    return j;
}

Partition写法二

将[left + 1, right]分成3个部分:

  • [left + 1, le)部分所有元素都 <= pivot

  • [le, ge]没有看到的部分

  • (ge, right]部分所有元素都 >= pivot

int partition(int *nums, int left, int right)
{
    int randomIndex = left + random(right - left + 1);
    swap(nums, left, randomIndex);
    
    int pivot = nums[left];
    int le = left + 1, ge = right;
    while (true) {
        while (le <= ge && nums[le] < pivot) {
            le++;
        }
        
        while (le <= ge && nums[ge] > pivot) {
            ge--;
        }
        
        if (le > ge) {
            break;
        }
        
        swap(nums, le, ge);
        le++;
        ge--;
    }
    
    swap(nums, left, ge);
    return ge;
}

Partition写法三

将[left + 1..right]被lt,gt分为四个部分

  • [left + 1..lt) < pivot;

  • [lt..i) = pivot

  • [i..gt]是程序还没有看到的部分

  • (gt..right] > pivot

void partition(int *nums, int left, int right, int *lowerBound, int *upperBound)
{
    int randomIndex = left + rand() % (right - left + 1);
    int pivot = nums[randomIndex];
    swap(nums, left, randomIndex);
​
    int lt = left + 1;
    int gt = right;
    int i = left + 1;
    while (i <= gt) {
        if (nums[i] < pivot) {
            swap(nums, lt, i);
            lt++;
            i++;
        } else if (nums[i] == pivot) {
            i++;
        } else {
            swap(nums, i, gt);
            gt--;
        }
    }
    swap(nums, left, lt - 1);
​
    *lowerBound = lt - 1;
    *upperBound = gt + 1;
}

Partition写法四

将[left + 1..right]按照lt,gt分为四个部分

  • [left+1, lt) < pivot;

  • [lt, gt) = pivot;

  • [gt..i] > pivot;

  • (i..right] 没有探索的区域

    void partition(int *nums, int left, int right, int *lowerBound, int *upperBound)
    {
        int randomIndex = left + rand() % (right - left + 1);
        int pivot = nums[randomIndex];
        swap(nums, left, randomIndex);
    ​
        int lt = left + 1;
        int gt = left + 1;
        for (int i = left + 1; i <= right; i++) {
            if (nums[i] < pivot) {
                swap(nums, lt, i);
                if (lt < gt) {
                    swap(nums, gt, i);
                }
                
                lt++;
                gt++;
            } else if (nums[i] == pivot) {
                swap(nums, gt, i);
                gt++;
            }
        }
        
        swap(nums, left, lt - 1);
        *lowerBound = lt - 1;
        *upperBound = gt;
    }

    Partition写法五

    填坑法,该方法类似写法二

    int partition(int *nums, int left, int right)
    {
        int randomIndex = left + rand() % (right - left + 1);
        int pivot = nums[randomIndex];
        swap(nums, left, randomIndex);
        
        int lt = left;
        int gt = right;
        while (lt < gt) {
            while (lt < gt && nums[gt] >= pivot) {
                gt--;
            }
            nums[lt] = nums[gt];
            
            while (lt < gt && nums[lt] < pivot) {
                lt++;
            }
            nums[gt] = nums[lt];
        }
        
        nums[lt] = pivot;
        return lt;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值