在STL中,经常用到的排序有两处:

 第一个是sort函数,容器要求是可以随机访问,像array,vector,deque,和普通数组。

第二个是部分排序容器的建立,例如map,set,priority_queue。

1、sort()函数

注意,下面的例子, sort(vec.begin(), vec.end(), cmp()),都加了括号,使用的是函数对象,更快。sort() 只对 array、vector、deque 和普通数组有支持。

1、对基本数据类型进行排序

1、默认方法

首先,sort() 函数,默认采用的是升序。less 是升序,greater 是降序。注意使用方法,其原型是函数对象的实现,因此注意写法。

vector<int> Vint = { 1,3,5,2,4,6 };
sort(Vint.begin(), Vint.end());                  {  1,2,3,4,5,6 }
//sort(Vint.begin(), Vint.end(), less<int>());   {  1,2,3,4,5,6 }

sort(Vint.begin(), Vint.end(), greater<int>());  { 6,5,4,3,2,1 }

 2、自定义方法,基本元素

struct shengxu{
    bool operator()(int a, int b){
        return a < b;
}

struct jiangxu{
    bool operator()(int a, int b){
        return a > b;
}

vector<int> Vint = { 1,3,5,2,4,6 }
sort(Vint.begin(), Vint.end(), shengxu());    { 1,2,3,4,5,6 }
sort(Vint.begin(), Vint.end(), jiangxu());    { 6,5,4,3,2,1 }

int N[] = { 1,3,5,2,4,6 };
sort(N, N+6, shengxu);    { 1,2,3,4,5,6 }
// sort 函数第二个参数要指向要排序元素截至后的一个字符。

3、对复杂元素进行排序 

struct node{
    string name;
    int age;
};
//先按name排序(升序),如果name相等,再按age排序(升序);
struct omp{
    bool operator()(node& a, node& b){
        if (a.string == b.string){
            return a.age < b.age;
        }
        return a.string < b.string;
}

node N[3] = {{"a",10},{"a",5},{"b",5}}
sort(N, N+3, omp());    {{"a",5},{"a",10},{"b",5}}

vector<node> nn(N, N+3); //怎样用数组创建vector
sort(nn.begin(), nn.end(), omp());    {{"a",5},{"a",10},{"b",5}}

2、map,set

1、set容器为例

1、默认方法

set 容器默认的存储的是升序。

set<int> Sint = { 1,3,2 };
for (auto it = Sint.begin(); it != Sint.end(); it++)
    cout << *it << "  ";
{ 1,2,3 }

set<int, greater<int>> Sint = { 1,3,2 };    { 3,2,1 }

 2、自定义

注意 set 排序的时候 ,函数要加 const

struct cmp{
    bool operator()(int a, int b) const{
        return a<b;
    }
};

set<int,cmp> Sint = { 1,3,2 };      { 1,2,3 }

3、对复杂元素

struct node {
	string name;
	int age;
};

struct cmp {
	bool operator() (node a, node b) const {
		if (a.name != b.name)
			return a.name < b.name;
		return a.age < b.age;
	}
};

int main()
{
	set<node, cmp> se;
	se.insert({ "a",10 });
	se.insert({ "a",5 });
	se.insert({ "b",5 });

	for (auto i = se.begin(); i != se.end(); i++) {
		cout << i->name << "  " << i->age << endl;
	}
	return 0;
}
输出:
a  5
a  10
b  5

 2、map容器

默认是对 key 值进行升序存储。

1、对 key 排序

1、对简单元素

默认是升序, less。 

struct cmp{
    bool operator() (int a, int b) const{
        return a > b; //降序
    }
};

int main()
{
    map<int,int,cmp> mp;
    mp[1] = 10;
    mp[4] = 3;
    mp[2] = 6;

    for(auto i = mp.begin(); i != mp.end(); i++) {
        cout << i->first << " " << i->second << endl;
    }
    return 0;
}
输出// 4 3
     2 6
     1 10
对key 进行降序

2、对结构体等复杂元素

	
struct node {
	string name;
	int age;
};

struct cmp {
	bool operator() (node a, node b) const {
		if (a.name != b.name)
			return a.name < b.name;
		return a.age < b.age;
	}
};

map<node, int, cmp> ma;
ma.insert({ { "a",10 } , 1 });
ma.insert({ { "a",5 } , 2 });
ma.insert({ { "b",5 } , 3 });

for (auto i = ma.begin(); i != ma.end(); i++) {
	cout << (i->first).name << "  " << (i->first).age << "  " << i->second << endl;
}

输出:
a  5  2
a  10  1
b  5  3

 2、对 value 排序

虽然不能直接用sort对map进行排序,那么我们可不可以迂回一下,把map中的元素放到序列容器(如vector)中,然后再对这些元素进行排序。

在此,要知道一个 数据,pair 数据类型。

template <class T1, class T2> struct pair;
pair <string, int> pair1("STL教程", 20);

pari1.first = "STL教程";
pari1.second = 20;

map<string,int> ma;
ma.insert(pari1);
struct node {
	string name;
	int age;
};

struct cmp1 {
	bool operator()(pair<node, int> a, pair<node, int> b) {
		return a.second > b.second;
	}
};

map<node, int, cmp> ma;
ma.insert({ { "a",10 } , 1 });
ma.insert({ { "a",5 } , 2 });
ma.insert({ { "b",5 } , 3 });

vector<pair<node, int>> v(ma.begin(), ma.end());
sort(v.begin(), v.end(), cmp1());

for (auto i : v) {
	cout << (i.first).name << "  " << (i.first).age << "  " << i.second << endl;
}
输出:
b  5  3
a  5  2
a  10  1

3、 priority_map

1、默认从大到小

int main()
{
    //创建一个空的priority_queue容器适配器
    std::priority_queue<int>values;
    //使用 push() 成员函数向适配器中添加元素
    values.push(3);//{3}
    values.push(1);//{3,1}
    values.push(4);//{4,1,3}
    values.push(2);//{4,2,3,1}
    //遍历整个容器适配器
    while (!values.empty())
    {
        //输出第一个元素并移除。
        std::cout << values.top()<<" ";
        values.pop();//移除队头元素的同时,将剩余元素中优先级最大的移至队头
    }
    return 0;
}
输出:
4 3 2 1

 2、自定义

struct cmp {
	bool operator()(int a, int b) const {
		return a > b;
	}
};
int main()
{
	int N[] = { 1,3,2,4 };
	priority_queue<int,vector<int>,cmp> myque(N,N+4);

	while (!myque.empty()) {
		cout << myque.top() << endl;
		myque.pop();
	}
	return 0;
}
输出: 1 2 3 4

3、对结构体排序

struct node{
    int age;
    string name;
    node(int a, string n):age(a),name(n){}
};
struct cmp {
    //先对年龄升序,年龄一样,对名字升序,注意是 >
    bool operator() (node& a, node& b) {
        if (a.age != b.age)
            return a.age > b.age;
        return a.name > b.name;
    }
};

int main()
{
    priority_queue<node, vector<node>, cmp> pque;
    pque.push(node(15,"zhangsan"));
    pque.push(node(13,"lisi"));
    pque.push(node(15,"lisi"));

    while(!pque.empty()) {
        cout << pque.top().age << " " << pque.top().name << endl;
        pque.pop();
    }

    return 0;
}
//输出:
13 lisi
15 lisi
15 zhangsan

4、总结

  • priority_queue 入队时候,排序的表示 和 其余不一样,刚好相反。
  • 使用函数对象 自己定义排序规则时, set 和 map 需要加 const;
  • priority_queue 在加自己定义的优先级时候,需要将第二个参数也声明;
  • 在添加自定义排序规则时,sort(v.begin(),v.end(), cmp());  set<int, cmp> se;
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐