与排序相关的STL模板

今天,深度学习了排序的我决定大展身手,将另我突发八十年脑血栓的STL排序全部列举出来.

本博客除了已在文章中说明的函数外,其他默认头文件为<algorithm>.

qsort

在c++标准库中,此函数被(收藏)于<cstdlib>

qsort 与 bsearch 的比较函数

qsort 函数有四个参数:数组名、元素个数、元素大小、比较规则。其中,比较规则通过指定比较函数来实现,指定不同的比较函数可以实现不同的排序规则。

比较函数的参数限定为两个 const void 类型的指针。返回值规定为正数、负数和 0。

比较函数的一种示例写法为:

int compare(const void *p1, const void *p2){
int *a=(int *)p1;
  int *b=(int*)p2;
  if(*a>*b)
    return 1; 
  else if(*a<*b)
    return -1; 
  else
    return 0;  
}

注意:返回用两个元素相减代表正负数是一种典型的错误写法,因为这样可能会有溢出的错误.

我之前就掉进坑过的,Please 大家不要重蹈覆辙哦,有前车之鉴的.

struct eg{
  int e;
  int g;
};
int compare(const void *p1,const void *p2){
  struct eg *a=(struct eg*)p1;
  struct eg *b=(struct eg*)p2;
  if (a->e>b->e)
    return 1; 
  else if (a->e<b->e)
    return -1; 
  else
    return 0; 
}

从这里也可以看出,等价并不代表相等哦!!只代表在此比较规则下两元素等价.

std::sort

用法:

// a[0] .. a[n - 1] 为需要排序的数列
// 对 a 原地排序,将其按从小到大的顺序排列
std::sort(a, a + n);

// cmp 为自定义的比较函数
std::sort(a, a + n, cmp);

注意:sort 的比较函数的返回值是 true 和 false,用 true 和 false 表示两个元素的大小(先后)关系,这与 qsort 的三值比较函数的语义完全不同。具体内容详见上方给出的 sort 的文档。

如果要将 sort 简单改写为 qsort,维持排序顺序整体上不变(不考虑等价的元素),需要将返回 true 改为 - 1,返回 false 改为 1。

std::sort 函数是更常用的 C++ 库比较函数。该函数的最后一个参数为二元比较函数,未指定 cmp 函数时,默认按从小到大的顺序排序。

旧版 C++ 标准中仅要求它的 平均 时间复杂度达到O(n log n) 。C++11 标准以及后续标准要求它的 最坏 时间复杂度达到O(n log n) 。

std::nth_element

用法如下:

std::nth_element(first, nth, last);
std::nth_element(first, nth, last, cmp);

它重排 [first, last) 中的元素,使得 nth 所指向的元素被更改为 [first, last) 排好序后该位置会出现的元素。这个新的 nth 元素前的所有元素小于或等于新的 nth 元素后的所有元素。

实现算法是未完成的内省排序。

对于以上两种用法,C++ 标准要求它的平均时间复杂度为O(n) ,其中 n 为 std::distance(first, last)

std::stable_sort

用法如下:

std::stable_sort(first, last);
std::stable_sort(first, last, cmp);

稳定排序,保证相等元素排序后的相对位置与原序列相同。

时间复杂度为O(n log n^{2}) ,当额外内存可用时,复杂度为 O(n log n)。

std::partial_sort

用法如下:

// mid = first + k
std::partial_sort(first, mid, last);
std::partial_sort(first, mid, last, cmp);

将序列中前 k 元素按 cmp 给定的顺序进行原地排序,后面的元素不保证顺序。未指定 cmp 函数时,默认按从小到大的顺序排序。

复杂度:约(last-first)log(mid-first)次应用 cmp

原理:

std::partial_sort 的思想是:对原始容器内区间为 [first, mid) 的元素执行 make_heap() 操作,构造一个大根堆,然后将 [mid, last) 中的每个元素和 first 进行比较,保证 first 内的元素为堆内的最大值。如果小于该最大值,则互换元素位置,并对 [first, mid) 内的元素进行调整,使其保持最大堆序。比较完之后,再对 [first, mid) 内的元素做一次堆排序 sort_heap() 操作,使其按增序排列。注意,堆序和增序是不同的。

自定义比较

内置类型(如 int)和用户定义的结构体允许定制调用 STL 排序函数时使用的比较函数。可以在调用该函数时,在最后一个参数中传入一个实现二元比较的函数。

对于用户定义的结构体,对其使用 STL 排序函数前必须定义至少一种关系运算符,或是在使用函数时提供二元比较函数。通常推荐定义 operator<

示例:

int a[1009], n = 10;
// ...
std::sort(a + 1, a + 1 + n);                  // 从小到大排序
std::sort(a + 1, a + 1 + n, greater<int>());  // 从大到小排序


struct data {
  int a, b;

  bool operator<(const data rhs) const {
    return (a == rhs.a) ? (b < rhs.b) : (a < rhs.a);
  }
} da[1009];

bool cmp(const data u1, const data u2) {
  return (u1.a == u2.a) ? (u1.b > u2.b) : (u1.a > u2.a);
}

// ...
std::sort(da + 1, da + 1 + 10);  // 使用结构体中定义的 < 运算符,从小到大排序
std::sort(da + 1, da + 1 + 10, cmp);  // 使用 cmp 函数进行比较,从大到小排序

由于临时写成,本篇文章未经过严格审批,如果文章有错误,望大家审批

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REAdMe.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看READme.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cqbzcyy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值