必须了解的编程基础-- 快速排序及C++模板函数实现

1. 快速排序的流程

  • 分组: 将序列分组,并保证该组的左端是小于主元的。自然地,右端要大于等于主元,然后返回主元的位置。这里选择一组中最右元素作为主元。这一过程使用双指针 i i i p o s pos pos实现,除了最后一步之外,指针 p o s pos pos始终指向右部的第一个元素,也就是指针 p o s pos pos左面的都是比主元小的元素。而指针 i i i负责不停地向右搜索比主元小的元素,并将其放到指针 p o s pos pos指向的位置。也就是将其和 p o s pos pos指向的元素交换位置。最后,将 p o s pos pos指向的元素和主元交换,也就是说,将主元放到右部的第一个位置上,从而保证了主元左部都是小于主元,而主元右部都是大于主元的。最终分组函数返回主元所在的位置下标。
  • 递归:不停对主元的左右两端重复分组操作。

2. C++实现快速排序

程序注释很清楚,使用模板函数实现。

/**
 * 使用模板函数实现一个快速排序
*/
#include <bits/stdc++.h>
using namespace std;

// 分组函数:升序排序保证左端元素小于主元,并返回主元位置
template <class T>
int partition(int left, int right, T& tar) {
    int pos = left;
    // 将left到right中小于主元的放到pos上
    for (int i = left; i < right; ++i) {
        if (tar[i] < tar[right]) {    // 如果降序排序,则将 < 改为 > 。保证左端元素大于主元。
            swap(tar[i], tar[pos]);
            pos ++;
        }
    }
    // 交换主元到中间,从而保证分组要求。
    swap(tar[pos], tar[right]);
    return pos;
}

// 快速排序,递归调用解决不同分组的排序问题
template <class T>
void qsort(int left, int right, T& tar) {
    if (left >= right) return ;
    int q = partition(left, right, tar);
    qsort(left, q-1, tar);
    qsort(q+1, right, tar);
}

主函数中测试样例:

int main() {
    // vector<int> a{2,3,7,4,5,6,1,0};    
    // qsort<vector<int>>(0, a.size(), a);    
    // vector<char> a{'b', 'a', 'c', 'd'};    
    // qsort<vector<char>>(0, a.size()-1, a);    
    int a[7] = {3, 2, 1, 4, 5, 6, 7};    
    qsort<int[sizeof(a)/sizeof(int)]>(0, 6, a); // qsort<int[7]>(0, 6, a);
    for (auto& e:a) { 
        cout << e << " ";    
    }    
    cout << endl;
}

总结

  1. 对于快速排序来说,其特点是递归的前进方向进行分组操作
  2. 而分组完成的任务是确定主元位置,以及保证主元的左部都是小于主元,而主元的右部都是大于主元。
  3. 从2.也可以得知,分组操作只能百分百保证排好一个元素的位置—主元。换句话说,一次分组操作中主元所处的位置就是最终排好序后的位置。
  4. 所以,需要分别对主元的左右两部再次进行分组操作,通过一次次分组操作,逐渐确定每一个主元的位置,直到最终分组中只剩下一个元素。而这个不断对主元左右两部进行分组的操作,正好可以通过递归实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值