C++进阶① :sort和优先级队列的比较函数、greater、less、substr、reverse

1 sort和优先级队列的自定义比较函数

C++自定义比较:比较函数、仿函数、重载操作符
sort函数
sort函数包含在头文件为#include< algorithm>的c++标准库中,默认升序。
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

优先级队列
优先级队列的a < b说明a的优先级不如b,优先队列里面是默认使用大根堆,也就是更大的数更优先。
priority, greater< a> >,a要完全一样。

比较函数的自定义方法

  1. sort函数取出两个值a、b,作为参数传到comp函数中去,如果返回值为true,则sort按照a-b的顺序排序,否则按b-a的顺序排序。 简单:按照true的顺序排序。
  2. 优先级队列取两个值a、b,如果返回值为true,则说明a < b,b优先于a。
  3. 比较函数内不能出现 <=,只能是 <

①静态compare函数
sort:

static bool compare(string& s1, string& s2){
       return s1+s2 < s2+s1;
}
sort(vs.begin(), vs.end(), compare);

优先级队列:注意用decltype(&cmp) q(cmp)

static bool cmp(pair<int, int>& m, pair<int, int>& n) {
        return m.second > n.second;
}
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> q(cmp);

②传入函数对象(仿函数)
函数对象是行为类似函数的对象。一个类对象,表现出一个函数的特征,即通过对象名+(参数列表)的方式使用一个类对象。

sort:有()

s1 = "2", s2 = "3", s1 + s2 = "23" < "32", s1放在s2前面才返回true,sort按照组合起来数字更小的顺序排序
struct compare{
        bool operator ()(string& s1, string& s2){
            return s1+s2 < s2+s1;
        }
};
sort(vs.begin(), vs.end(), compare()); / 注意有()

优先级队列:无()

如果a.second < b.second,返回true,即a < b,即b更优先,此处是second更大的更优先
另一种思路,对于sort此处是second更小的排在前面,优先级队列相反,所以是second更大的排在前面。
struct compare{
        bool operator ()(pair<int, int>& a, pair<int, int>& b){
            return a.second < b.second;
        }
};
priority_queue<pair<int, int>, vector<pair<int, int>>, compare> pq;

如果a->val < b->val,返回false,即a > b,即a更优先,此处是val更小的更优先。
另一种思路,对于sort此处是val更大的排在前面,优先级队列相反,所以val更小的排在前面。
struct compare{
        bool operator ()(ListNode* a, ListNode* b){
            return a->val > b->val;
        }
};

③重载 <
这种方式使得复杂结构变得像基本数据类型一样可比较了。这样就不用传比较器了,因为默认的比较器这时已经生效了。对于 cpp 代码,重载运算符不管对于 struct 还是 class 都是很方便的,都是在自己定义的结构体或类类型里加一个重载的函数即可。

④lambda表达式法

sort:a > b才返回true,才能按照a-b的顺序排列,所以此处为降序
sort(vs.begin(), vs.end(), [](int a, int b){return a > b;});

stable_sort 稳定排序

相同元素排序前后相对位置不变。
不要用greater排序pair,用自定义cmp函数,或者仿函数。
stable_sort的自定义比较函数一定要写const。 也建议sort写自定义函数的时候都加上const。

2 greater<>()、less<>()的基本用法

sort和优先级队列对元素的呈现形式是相反的
对于priority_queue,更优先的元素在前端,默认情况下与less<>()相同,更大的数更优先。
但如果第三个参数为greater<>() 或者重载了()、或者重载了 < 、更小的的数更优先。

方法1:
// 按pair的第二个元素降序排列
 static bool cmp(pair<int,int> a, pair<int, int> b){
    return a.second > b.second;
}
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> q(cmp);

方法2:
 struct cmp1{
    bool operator()(pair<int,int> a, pair<int, int> b){
        return a.second > b.second;
    }
};
priority_queue<pair<int,int> , vector<pair<int,int>>, cmp1> q;



priority_queue<int> q;//默认是从大到小

priority_queue<int, vector<int> ,less<int> >q;//从大到小排序

priority_queue<int, vector<int>, greater<int> >q;//从小到大排序
#include 
#include 
#include 
#include 
using namespace std;

int main() {
	int a[] = { 3, 5, 6, 2, 1, 4 };
	sort(a, a + 6);
	cout << "sort默认:";
	for (auto e : a)
		cout << e << "  ";
	cout << endl;

	sort(a, a + 6, greater<int>());
	cout << "sort_greater:";
	for (auto e : a)
		cout << e << "  ";
	cout << endl;

	sort(a, a + 6, less<int>());
	cout << "sort_less:";
	for (auto e : a)
		cout << e << "  ";
	cout << endl;

	priority_queue<int> mypriqueue;
	int b[] = { 3, 5, 6, 2, 1, 4 };
	for (auto e : b) {
		mypriqueue.push(e);
	}
	cout << "优先级队列默认:";
	while (!mypriqueue.empty()) {
		cout << mypriqueue.top() << "  ";
		mypriqueue.pop();
	}
	cout << endl;


	priority_queue<int, vector<int>, greater<int>> q1;
	for (auto e : b)
		q1.push(e);
	cout << "优先级队列_greater:";
	while (!q1.empty()) {
		cout <<q1.top() << "  ";
		q1.pop();
	}
	cout << endl;

	priority_queue<int, vector<int>, less<int>> q2;
	for (auto e : b)
		q2.push(e);
	cout << "优先级队列_less:";
	while (!q2.empty()) {
		cout << q2.top() << "  ";
		q2.pop();
	}
	return 0;
}
输出:
sort默认:1  2  3  4  5  6
sort_greater:6  5  4  3  2  1
sort_less:1  2  3  4  5  6
优先级队列默认:6  5  4  3  2  1
优先级队列_greater:1  2  3  4  5  6
优先级队列_less:6  5  4  3  2  1

3 substr用法

  1. 形式:s.substr(pos, n)
  2. 解释:返回一个string,包含s中从pos开始的n个字符的拷贝(pos的默认值是0,n的默认值是s.size() - pos,即不加参数会默认拷贝整个s)
  3. 补充:若pos的值超过了string的大小,则substr函数会抛出一个out_of_range异常;若pos+n的值超过了string的大小,则substr会调整n的值,只拷贝到string的末尾

4 reverse

包含在< alogotithm > 中
reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数没有返回值

5 advance

advance(it, n)
it 表示某个迭代器,n 为整数。该函数的功能是将 it 迭代器前进或后退 n 个位置。
n为正数,则前进(右移);n为负数,则后退(左移)。
advance() 函数本身不会检测 it 迭代器移动 n 个位置的可行性,如果 it 迭代器的移动位置超出了合理范围,it 迭代器的指向将无法保证,此时使用 *it 将会导致程序崩溃。

你可能感兴趣的:(C++进阶,c++)