stable_sort()函数易错点

释义

  该函数接受三个参数,stable_sort(first ,last ,cmp)(这里只是简单表示一下,并不是函数原型, cmp可以不用,默认为升序);这个函数的作用是对容器进行排序,并保证其稳定性(相等元素排序前后的相对位置不变)。

Sorts the elements in the range [__first,__last) in ascending order, such that for each iterator i in the range [__first,__last-1), __comp((i+1),i) is false. The relative ordering of equivalent elements is preserved, so any two elements x and y in the range [__first,__last) such that __comp(x,y) is false and __comp(y,x) is false will have the same relative ordering after calling stable_sort().

问题

cmp参数

  下面是关于cmp函数的相关介绍

Binary function that accepts two elements in the range as arguments, and returns a value convertible to `bool`. The value returned indicates whether the element passed as first argument is considered to go before the second in the specific _strict weak ordering_ it defines.  
The function shall not modify any of its arguments.  
This can either be a function pointer or a function object.

  cmp()函数的参数不可以是引用(但可以用是 常引用 或 值传递)举一个例子吧

	/* 省略函数体 */
	bool cmp_1(int x, int y){}    //值传递,允许
	bool cmp_2(const int &x, const int &y){} //常引用,允许
	bool cmp_3(int &x, int &y){} //引用,不允许

cmp比较源码

  这里有一些让人费解的地方,对于以下两个函数来说,stable_sort()产生的结果是一样的吗?

bool cmp_1(int x,int y) {
		return x > y;
}

bool cmp_2(int x,int y) {
		return x >= y;
}

  思考一下,如果传入 x 的值和传入 y 的值在相等的情况下是否是一样的(这里包括稳定性),举个例子(用结构体帮助观察相对位置是否发生改变)

#include <iostream>  
#include <vector>  
#include <string>  
#include <algorithm>  
  
struct Student {  
    std::string str;  
    int num;  
};  
  
bool cmp_1(const Student &x, const Student &y) { return x.num > y.num; }  

bool cmp_2(const Student &x, const Student &y) { return x.num >= y.num; }  
  
int main() {  
    auto *p = new Student[]{{"a", 2},  
                            {"b", 2}};  
	/* 正确 */
    std::stable_sort(p, p + 2, cmp_1);  
    std::cout << p->str << ' ' << (p + 1)->str << std::endl;  
	
	/* 错误 */
    std::stable_sort(p, p + 2, cmp_2);  
    std::cout << p->str << ' ' << (p + 1)->str;  
    
    delete[] p;  
    return 0;  
}


/*
输出的结果是:
	a b
	b a
*/

  可以看出 cmp_1 和 cmp_2 的结果是不同的,为什么 cmp_2 作为参数时stable_sort()不保证容器的稳定性呢? 这涉及到”函数源码“了?


Sorts the elements in the range [__first,__last) in ascending order, such that for each iterator i in the range [__first,__last-1), __comp(*(i+1),*i) is false.

  这里要保证 __comp(*(i+1),*i) is false,这个与我一直以为的__comp(*i,*(i+1)) is true 是不同的,所以 cmp_ 2 return x >= y 在遇到相等元素时会返回 true 不满足这个要求,所以会出错,这是第一个要注意的点。

第二个要注意的是满足Strict Weak Ordering 有以下几点要求:
1.Irreflexivity: f(x, x) must be false.
2.Antisymmetry: f(x, y) implies !f(y, x)
3.Transitivity: f(x, y) and f(y, z) imply f(x, z).

参考

  1. https://cplusplus.com/reference/algorithm/stable_sort/
  2. https://www.boost.org/sgi/stl/StrictWeakOrdering.html
posted @ 2024-04-16 01:12  KK_LOVE  阅读(3)  评论(0编辑  收藏  举报