9.手写sort(模仿源码)

手写sort(模仿源码)

版本一:快速排序

/*************************************************************************
        > File Name: test1.cpp
        > Author:Xiao Yuheng
        > Mail:3312638794@qq.com
        > Created Time: Sat Nov  4 10:48:10 2023
 ************************************************************************/

#include <iostream>
#include <functional>

using namespace std;

bool cmp1(int a, int b) {
    return a < b;
}

bool cmp2(int a, int b) {
    return a > b;
}

void __quick_sort(int *first, int *last, function<bool(int, int)> cmp = less<int>()) {
    if (first >= last) return ;
    int *l = first, *r = last - 1, value = *first;
    while (l < r) {
        while (l < r && cmp(value, *r)) r--;
        if (l < r) *(l++) = *r;
        while (l < r && cmp(*l, value)) l++;
        if (l < r) *(r--) = *l;
    }
    *l = value;
    __quick_sort(first, l, cmp);
    __quick_sort(l + 1, last, cmp);
    return ;
}

void sort(int *first, int *last, function<bool(int, int)> cmp = less<int>()) {
    __quick_sort(first, last, cmp);
    return ;
}

void output(int *first, int *last, const char *str) {
    cout << str << " = ";
    while (first < last) {
        cout << *(first++) << " ";
    }
    cout << endl;
    return ;
}

int main() {
    int n, a[10020];
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];
    sort(a, a + n, cmp1);
    output(a, a + n, "cmp1");
    sort(a, a + n, cmp2);
    output(a, a + n, "cmp2");
    return 0;
}

__quick_sort函数:

cppCopy codevoid __quick_sort(int *first, int *last, function<bool(int, int)> cmp = less<int>()) {
    if (first >= last) return ;
    int *l = first, *r = last - 1, value = *first;
    while (l < r) {
        while (l < r && cmp(value, *r)) r--;
        if (l < r) *(l++) = *r;
        while (l < r && cmp(*l, value)) l++;
        if (l < r) *(r--) = *l;
    }
    *l = value;
    __quick_sort(first, l, cmp);
    __quick_sort(l + 1, last, cmp);
    return ;
}
  • 这是一个递归的快速排序算法。它接受三个参数:
    • int *first:指向待排序范围的起始位置的指针。
    • int *last:指向待排序范围的结束位置的下一个位置的指针。
    • function<bool(int, int)> cmp = less<int>():一个比较函数,默认为less<int>(),表示默认按照升序排列。
  • 首先,它检查了firstlast的关系,如果first >= last,说明排序范围为空或者只有一个元素,无需进行排序,直接返回。
  • 然后,它选择了first指向的元素作为基准值value
  • 接着,它使用两个指针lr分别指向排序范围的开始和结束位置。
  • 然后,它开始进行分区操作,将比基准值大的元素放在右侧,比基准值小的元素放在左侧。
  • 最后,它递归调用自身,对分区后的子数组进行排序。

我们这里调用sort函数来进行排序,现在sort内部只有一个快速排序,我们我们接着来进行优化。

版本二:优化快排

/*************************************************************************
        > File Name: test1.cpp
        > Author:Xiao Yuheng
        > Mail:3312638794@qq.com
        > Created Time: Sat Nov  4 10:48:10 2023
 ************************************************************************/

#include <iostream>
#include <functional>

using namespace std;

bool cmp1(int a, int b) {
    return a < b;
}

bool cmp2(int a, int b) {
    return a > b;
}

void __quick_sort(int *first, int *last, function<bool(int, int)> cmp = less<int>()) {
    while (first < last) {
        int *l = first, *r = last - 1;
        int value = *first;
        do{
            while (cmp(*l, value)) l++;
            while (cmp(value, *r)) r--;
            if (l <= r) swap(*(l++), *(r--));
        } while (l <= r);
        __quick_sort(l, last, cmp);
        last = r + 1;
    }
    return ;
}

void sort(int *first, int *last, function<bool(int, int)> cmp = less<int>()) {
    __quick_sort(first, last, cmp);
    return ;
}

void output(int *first, int *last, const char *str) {
    cout << str << " = ";
    while (first < last) {
        cout << *(first++) << " ";
    }
    cout << endl;
    return ;
}

int main() {
    int n, a[10020];
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];
    sort(a, a + n, cmp1);
        output(a, a + n, "cmp1");
    sort(a, a + n, cmp2);
    output(a, a + n, "cmp2");
    return 0;
}

优化方法为单边递归无监督优化,详细解释:【精选】十大排序算法(C++)_c++排序算法-CSDN博客

版本三:插入排序优化

/*************************************************************************
        > File Name: test1.cpp
        > Author:Xiao Yuheng
        > Mail:3312638794@qq.com
        > Created Time: Sat Nov  4 10:48:10 2023
 ************************************************************************/

#include <iostream>
#include <functional>

using namespace std;

bool cmp1(int a, int b) {
    return a < b;
}

bool cmp2(int a, int b) {
    return a > b;
}

const int threshold = 16;

void __quick_sort(int *first, int *last, function<bool(int, int)> cmp = less<int>()) {
    while (last - first > threshold) {
        int *l = first, *r = last - 1, value = *first;
        do{
            while (cmp(*l, value)) l++;
            while (cmp(value, *r)) r--;
            if (l <= r) swap(*(l++), *(r--));
        } while (l <= r);
        __quick_sort(l, last, cmp);
        last = r + 1;
    }
    return ;
}

void insertion_sort(int *first, int *last, function<bool(int, int)> cmp = less<int>()) {
    int *ind = first;
    for (int *i = first + 1; i < last; i++) {
        if (cmp(*i, *ind)) ind = i;
    }
    while (ind != first) {
        swap(*ind, *(ind - 1));
        ind--;
    }
    for (int *i = first + 2; i < last; i++) {
        int *j = i;
        while (cmp(*j, *(j - 1))) {
            swap(*j, *(j - 1));
            j--;
        }
    }
    return ;
}

void sort(int *first, int *last, function<bool(int, int)> cmp = less<int>()) {
    __quick_sort(first, last, cmp);
    insertion_sort(first, last, cmp);
    return ;
}

void output(int *first, int *last, const char *str) {
    cout << str << " = ";
    while (first < last) {
        cout << *(first++) << " ";
    }
    cout << endl;
    return ;
}

int main() {
    int n, a[10020];
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];
    sort(a, a + n, cmp1);
    output(a, a + n, "cmp1");
    sort(a, a + n, cmp2);
    output(a, a + n, "cmp2");
    return 0;
}
  1. 插入排序的引入:

    为了提高性能,当待排序范围的大小小于 threshold 时,切换到插入排序算法。插入排序在小规模数据上比快速排序更高效,因为它的时间复杂度是 O(n^2),但是常数因子比快速排序小。

    cppCopy codevoid insertion_sort(int *first, int *last, function<bool(int, int)> cmp = less<int>()) {
        int *ind = first;
        for (int *i = first + 1; i < last; i++) {
            if (cmp(*i, *ind)) ind = i;
        }
        while (ind != first) {
            swap(*ind, *(ind - 1));
            ind--;
        }
        for (int *i = first + 2; i < last; i++) {
            int *j = i;
            while (cmp(*j, *(j - 1))) {
                swap(*j, *(j - 1));
                j--;
            }
        }
        return ;
    }
    

    插入排序中也引用了无监督优化

版本四:手动实现RandomIter迭代器

/*************************************************************************
        > File Name: test1.cpp
        > Author:Xiao Yuheng
        > Mail:3312638794@qq.com
        > Created Time: Sat Nov  4 10:48:10 2023
 ************************************************************************/

#include <iostream>
#include <functional>

using namespace std;

bool cmp1(int a, int b) {
    return a < b;
}

bool cmp2(int a, int b) {
    return a > b;
}

const int threshold = 16;

class RandomIter {
public:
    RandomIter(int *ptr) : ptr(ptr) {}
    int operator-(RandomIter &ran) { return ptr - ran.ptr; }
    RandomIter operator-(int x) { return ptr - x; }
    RandomIter operator+(int x) { return ptr + x; }
    int &operator*() { return *ptr; }
    RandomIter operator++(int) { return ptr++; }
    RandomIter operator--(int) { return ptr--; }
    // 运用小于号来重载 > <= >=
    bool operator<(RandomIter &iter) { return ptr < iter.ptr; }
    bool operator>(RandomIter &iter) { return iter < *this; }
    bool operator<=(RandomIter &iter) { return !(iter < *this); }
    bool operator>=(RandomIter &iter) { return !(*this < iter); }
    bool operator!=(RandomIter &iter) { return (*this < iter) || (iter < *this); }
    bool operator==(RandomIter &iter) { return !(*this < iter) && !(iter < *this); }
private:
    int *ptr;
};

void __quick_sort(RandomIter first, RandomIter last, function<bool(int, int)> cmp = less<int>()) {
    while (last - first > threshold) {
        RandomIter l = first, r = last - 1;
        int value = *first;
        do{
            while (cmp(*l, value)) l++;
            while (cmp(value, *r)) r--;
            if (l <= r) swap(*(l++), *(r--));
        } while (l <= r);
        __quick_sort(l, last, cmp);
        last = r + 1;
    }
    return ;
}

void insertion_sort(RandomIter first, RandomIter last, function<bool(int, int)> cmp = less<int>()) {
    RandomIter ind = first;
        for (RandomIter i = first + 1; i < last; i++) {
        if (cmp(*i, *ind)) ind = i;
    }
    while (ind != first) {
        swap(*ind, *(ind - 1));
        ind--;
    }
    for (RandomIter i = first + 2; i < last; i++) {
        RandomIter j = i;
        while (cmp(*j, *(j - 1))) {
            swap(*j, *(j - 1));
            j--;
        }
    }
    return ;
}

void sort(RandomIter first, RandomIter last, function<bool(int, int)> cmp = less<int>()) {
    __quick_sort(first, last, cmp);
    insertion_sort(first, last, cmp);
    return ;
}

void output(int *first, int *last, const char *str) {
    cout << str << " = ";
    while (first < last) {
        cout << *(first++) << " ";
    }
    cout << endl;
    return ;
}

int main() {
    int n, a[10020];
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];
    sort(a, a + n, cmp1);
        output(a, a + n, "cmp1");
    sort(a, a + n, cmp2);
    output(a, a + n, "cmp2");
    return 0;
}
  1. 优点:
    • 提高了代码的可读性和可维护性,减少了指针操作的复杂性,使代码更易理解。
    • 使代码更加通用,可以应用于不同数据类型的容器,而不仅限于整型数组。
    • 通过 RandomIter 类的运算符重载,提供了一种更面向对象的方式来处理数组元素,使代码更具面向对象编程(OOP)的特性。
    • 通过使用迭代器类,代码现在更加具有扩展性,能够适用于不同的数据结构和容器。

版本五:快排优化

/*************************************************************************
        > File Name: test1.cpp
        > Author:Xiao Yuheng
        > Mail:3312638794@qq.com
        > Created Time: Sat Nov  4 10:48:10 2023
 ************************************************************************/

#include <iostream>
#include <functional>

using namespace std;

bool cmp1(int a, int b) {
    return a < b;
}

bool cmp2(int a, int b) {
    return a > b;
}

const int threshold = 16;

class RandomIter {
public:
    RandomIter(int *ptr) : ptr(ptr) {}
    int operator-(RandomIter &ran) { return ptr - ran.ptr; }
    RandomIter operator-(int x) { return ptr - x; }
    RandomIter operator+(int x) { return ptr + x; }
    int &operator*() { return *ptr; }
    RandomIter operator++(int) { return ptr++; }
    RandomIter operator--(int) { return ptr--; }
    // 运用小于号来重载 > <= >=
    bool operator<(RandomIter &iter) { return ptr < iter.ptr; }
    bool operator>(RandomIter &iter) { return iter < *this; }
    bool operator<=(RandomIter &iter) { return !(iter < *this); }
    bool operator>=(RandomIter &iter) { return !(*this < iter); }
    bool operator!=(RandomIter &iter) { return (*this < iter) || (iter < *this); }
    bool operator==(RandomIter &iter) { return !(*this < iter) && !(iter < *this); }
private:
    int *ptr;
};

int Get_mid(RandomIter first, RandomIter last) {
    int a = *first;
    int b = *(last - 1);
    int c = *(first + ((last - first) >> 1));
    if (a > b) swap(a, b);
    if (a > c) swap(a, c);
    if (b > c) swap(b, c);
    return b;
}

void __quick_sort(RandomIter first, RandomIter last, function<bool(int, int)> cmp = less<int>()) {
    while (last - first > threshold) {
        RandomIter l = first, r = last - 1;
        // int value = *first;
        int value = Get_mid(first, last);
        do{
            while (cmp(*l, value)) l++;
            while (cmp(value, *r)) r--;
            if (l <= r) swap(*(l++), *(r--));
        } while (l <= r);
        __quick_sort(l, last, cmp);
        last = r + 1;
    }
    return ;
}

void insertion_sort(RandomIter first, RandomIter last, function<bool(int, int)> cmp = less<int>()) {
    RandomIter ind = first;
        for (RandomIter i = first + 1; i < last; i++) {
        if (cmp(*i, *ind)) ind = i;
    }
    while (ind != first) {
        swap(*ind, *(ind - 1));
        ind--;
    }
    for (RandomIter i = first + 2; i < last; i++) {
        RandomIter j = i;
        while (cmp(*j, *(j - 1))) {
            swap(*j, *(j - 1));
            j--;
        }
    }
    return ;
}

void sort(RandomIter first, RandomIter last, function<bool(int, int)> cmp = less<int>()) {
    __quick_sort(first, last, cmp);
    insertion_sort(first, last, cmp);
    return ;
}

void output(int *first, int *last, const char *str) {
    cout << str << " = ";
    while (first < last) {
        cout << *(first++) << " ";
    }
    cout << endl;
    return ;
}

int a[10000020];

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];
    sort(a, a + n, cmp1);
    output(a, a + n, "cmp1");
    sort(a, a + n, cmp2);
    output(a, a + n, "cmp2");
    return 0;
}

引入了 Get_mid 函数:

cppCopy codeint Get_mid(RandomIter first, RandomIter last) {
    int a = *first;
    int b = *(last - 1);
    int c = *(first + ((last - first) >> 1));
    if (a > b) swap(a, b);
    if (a > c) swap(a, c);
    if (b > c) swap(b, c);
    return b;
}
  • 这个函数用于选择中值元素。它接受两个 RandomIter 对象,分别指向待排序范围的起始位置和结束位置。
  • 该函数计算了首、尾和中间三个位置的元素,并确保 a <= b <= c,返回 b 作为中值元素。
  • 确保每次的value都是有意义的。
  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值