快速排序算法中的Lomuto分区

一 概述

          Lomuto 分区方案是快速排序算法中常用的一种分区策略,由 Nico Lomuto 提出。它的核心思想是通过一次遍历将数组划分为两个子数组,使得左子数组的元素均小于等于基准值(pivot),右子数组的元素均大于基准值。

二  Lomuto 分区的步骤
1  选择基准值(pivot)  
   通常选择当前子数组的最后一个元素作为基准值(也可优化为随机选择)。

2  初始化指针  
   定义指针 i,初始指向子数组的起始位置 low - 1。i的作用是标记小于等于基准值的子数组的末尾。

3  遍历数组
   使用指针 j从左到右遍历子数组 [low, high-1],逐个比较元素与基准值:
    若 arr[j] ≤ pivot,则 i 自增 1,并交换 arr[i] 和 arr[j]。
   若 arr[j] > pivot,直接跳过。

4   放置基准值:  
   遍历完成后,将基准值 arr[high] 交换到 i+1 的位置。此时:
     [low, i]的元素均 ≤ pivot,
      [i+2, high]的元素均 > pivot,
       i+1是基准值的最终位置。

 

二 代码实现


#include <iostream>
using namespace std;

void swap(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}

int partition(int arr[], int low, int high) {
    int pivot = arr[high]; // 选择最后一个元素作为基准
    int i = low - 1; // 指向比基准小的元素的末尾
    for (int j = low; j <= high - 1; j++) {
        if (arr[j] < pivot) {
            i++;
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[i + 1], arr[high]); // 将基准放到正确位置
    return i + 1;
}

三  示例演示
     假设数组为 [3, 7, 2, 5, 1, 4],选择最后一个元素 4作为基准:
    遍历过程:
     j=0, 元素 3 ≤ 4→ i=0, 交换 arr[0] 和自身 → 数组不变。
     j=1, 元素 7 > 4 → 无操作。
     j=2, 元素 2 ≤ 4→ i=1, 交换 arr[1]和 arr[2] → 数组变为 [3, 2, 7, 5, 1, 4]。
    j=3, 元素 5 > 4 → 无操作。
    j=4, 元素 1 ≤ 4 → i=2, 交换 arr[2]和 arr[4] → 数组变为 [3, 2, 1, 5, 7, 4]。
    放置基准值:交换 i+1=3和 high=5→ 数组变为 [3, 2, 1, 4, 7, 5]。

       最终基准值 4位于索引 3,左子数组 [3, 2, 1]≤ 4,右子数组 [7, 5]> 4。

 

四  时间复杂度
     平均情况:(O(n)),单次分区需遍历整个子数组。

五  优缺点
1 优点
     实现简单,逻辑清晰。
     适合教学和小规模数据。
2  缺点
   对已有序数组效率低下(需优化基准选择)。
  重复元素较多时性能较差(Hoare 分区更高效)。

 

六  优化建议
1  随机化基准  
   随机选择 pivot而非固定最后一个元素,减少最坏情况概率。
   

2  三数取中法 
   取子数组首、中、尾三元素的中位数作为基准,进一步平衡分区。

 

七  与 Hoare 分区的对比
特性         Lomuto 分区              Hoare 分区              
实现复杂度    简单                         较复杂                    
交换次数    较多(每次交换需移动元素) 较少                  
重复元素处理    效率低                    更高效       

基准位置  固定为子数组末尾   初始位置或中间   

        Lomuto 分区是理解快速排序的基础,但在实际应用中,结合随机化基准或 Hoare 分区能显著提升性能。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kupeThinkPoem

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值