C++ sort 函数 以及 priority_queue 的使用
本人在日常使用 C++ 编写程序时,经常有对 sort
和 priority_queue
的使用感到模棱两可的情况,一忍再忍,忍无可忍,整理出二者常用用法,一方面供自己日后感到困惑时复习,一方面希望帮到一样感到困惑的读者朋友。如有不当之处,敬请体谅。
1. sort 函数的使用
sort 函数的定义:
#include <algorithm> //头文件
sort (first, end, compare);
- sort 对 [first, end) 范围内的元素进行排序。
- 默认为升序排序(此时不需要传入compare)。
- 当需要降序排序时,需要传入比较器 compare。
1.1 普通数组
升序
代码:
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int array[10];
for(int i = 0; i < 10; i++) array[i] = 9 - i;
printf("=====排序前=====\n");
for(int i = 0; i < 10; i++) printf("%d ", array[i]);
puts("");
sort(array,array + 10);
printf("=====排序后=====\n");
for(int i = 0; i < 10; i++) printf("%d ", array[i]);
puts("");
return 0;
}
输出结果:
降序
代码:
#include <iostream>
#include <algorithm>
using namespace std;
bool cmp(int a, int b)
{
return a > b;
}
int main()
{
int array[10];
for(int i = 0; i < 10; i++) array[i] = i;
printf("=====排序前=====\n");
for(int i = 0; i < 10; i++) printf("%d ", array[i]);
puts("");
sort(array,array + 10, cmp);
printf("=====排序后=====\n");
for(int i = 0; i < 10; i++) printf("%d ", array[i]);
puts("");
return 0;
}
输出结果:
此时为降序排序,需传入比较器 compare。
compare: 一个返回值为 bool 类型的函数。
如代码中 cmp 所写:
- 假定排序完成后的降序是从 左 到 右。
- 需要比较的两个数 a , b 在数组的相对位置为 a 在左, b 在右。
- return true 则代表二者相对位置正确,不需要改变。
- return false 则代表二者相对位置错位,需要改变。
1.2 结构体数组
升序
代码:
#include <iostream>
#include <algorithm>
using namespace std;
struct Student
{
int age;
int score;
bool operator<(const Student& student) const
{
return age < student.age;
}
};
int main()
{
Student students[10];
for(int i = 0; i < 10; i++)
{
students[i].age = 9 - i;
students[i].score = 0;
}
printf("=====排序前=====\n");
for(int i = 0; i < 10; i++) printf("%d ", students[i].age);
puts("");
sort(students,students + 10);
printf("=====排序后=====\n");
for(int i = 0; i < 10; i++) printf("%d ", students[i].age);
return 0;
}
输出结果:
sort 默认为升序排序,当我们期望升序排序时,可以不传入 compare 比较器,只需要重载 < 运算符。
重载 < 运算符的函数返回值为 bool 类型。
- 假定排序完成后的升序是 从 左 到 右。
- *this(当前Student) 和 要比较的Student 的相对位置为 *this 在左, student 在右。
- return true: 二者相对位置正确,不需要改变。
- return fasle: 二者相对位置错误,需要改变。
降序
代码:
#include <iostream>
#include <algorithm>
using namespace std;
struct Student
{
int age;
int score;
};
bool cmp(const Student& a, const Student& b)
{
return a.age > b.age;
}
int main()
{
Student students[10];
for(int i = 0; i < 10; i++)
{
students[i].age = i;
students[i].score = 0;
}
printf("=====排序前=====\n");
for(int i = 0; i < 10; i++) printf("%d ", students[i].age);
puts("");
sort(students,students + 10, cmp);
printf("=====排序后=====\n");
for(int i = 0; i < 10; i++) printf("%d ", students[i].age);
puts("");
return 0;
}
输出结果:
sort 默认为升序排序,当我们期望降序排序时,需要传入 compare 比较器。
如 cmp, 比较器为一个返回值为 bool 类型的函数。
- 假定排序完成后的降序是 从 左 到 右。
- Student a 和 Student b 的相对位置为 a 在左, b 在右。
- return true: 二者相对位置正确,不需要改变。
- return fasle: 二者相对位置错误,需要改变。
混合排序:
仅以一种情况作为说明。
先比较成绩,成绩高的排在前面(成绩降序),若成绩相同,则比较年龄,年龄小的排在前面(年龄升序)。
bool cmp(const Student& a, const Student& b)
{
if(a.score == b.score)
return a.age < b.age;
else
return a.score > b.score;
}
sort(students,students + 10, cmp);
sort 默认为升序排序,当我们期望混合排序时,需要传入 compare 比较器。
如 cmp, 比较器为一个返回值为 bool 类型的函数。
- 假定排序完成后的降序是 从 左 到 右。
- Student a 和 Student b 的相对位置为 a 在左, b 在右。
- return true: 二者相对位置正确,不需要改变。
- return fasle: 二者相对位置错误,需要改变。
1.3 标准库容器
以 vector 为例:
// 内置类型:int, double , string ... 等重载过 < 的类型
vector<int> vec1;
//升序:
sort(vec1.begin(),vec.end());
//降序:
bool cmp(int a, int b)
{
return a > b;
}
sort(vec1.begin(),vec1.end(),cmp);
// 自定义类型
vector<Student> vec2;
// 升序:
struct Student
{
int age;
int score;
bool operator<(const Student& student) const
{
return age < student.age;
}
};
sort(vec2.begin(),vec2.end());
// 降序:
bool cmp(const Student& a, const Student& b)
{
return a.age > b.age;
}
sort(vec2.begin(),vec2.end(),cmp);
2. priority_queue 的使用
priority_queue 一般当作堆来使用。
priority_queue的定义:
换成人话就是,以堆中存放 int 类型数据为例
#include <queue> // 头文件
priority_queue<int, vector<int>, less<int>>;
- 第一个参数代表堆中数据类型。
- 第二个参数代表底层使用的容器,默认为 vector, 可选为deque。
- 第三个参数代表堆的类型,大顶堆(less<Type>)还是小顶堆(greater<Type>),默认为大顶堆(less<Type>)。
2.1 内置类型
小顶堆
代码:
#include <iostream>
#include <queue>
using namespace std;
int main()
{
priority_queue<int,vector<int>,greater<int>> pq; // 小顶堆
printf("=====插入的顺序=====\n");
for(int i = 10; i >= 1; i--)
{
printf("%d ", i);
pq.push(i);
}
puts("");
printf("=====输出的顺序=====\n");
while(pq.size())
{
printf("%d ", pq.top());
pq.pop();
}
puts("");
return 0;
}
输出结果:
大顶堆
#include <iostream>
#include <queue>
using namespace std;
int main()
{
priority_queue<int,vector<int>> pq;
// priority_queue<int,vector<int>,greater<int>> pq; //大顶堆
// 默认为 greater<int>,可以不加。
printf("=====插入的顺序=====\n");
for(int i = 1; i <= 10; i++)
{
printf("%d ", i);
pq.push(i);
}
puts("");
printf("=====输出的顺序=====\n");
while(pq.size())
{
printf("%d ", pq.top());
pq.pop();
}
puts("");
return 0;
}
输出结果:
2.2 自定义类型
内置类型如 char, int , double, string...等往往重载了 > 和 < 运算符。
当使用自定义类型构建堆时,由于堆的大小元素比较,需重载对应的运算符。
- 小顶堆,定义时 greater<Type>, 重载 > 运算符。
- 大顶堆,定义时 less<Type>, 重载 < 运算符。
小顶堆
代码:
#include <iostream>
#include <queue>
using namespace std;
struct Student
{
int age;
int score;
bool operator > (const Student& student) const
{
return age > student.age;
}
};
int main()
{
priority_queue<Student,vector<Student>,greater<Student>> pq;
printf("=====插入元素的顺序=====\n");
for(int i = 10; i >= 1; i--)
{
printf("%d ", i);
Student* stu = new Student({i,0});
pq.push(*stu);
}
puts("");
printf("=====输出元素的顺序=====\n");
while(pq.size())
{
Student stu = pq.top();
printf("%d ", stu.age);
pq.pop();
}
puts("");
return 0;
}
输出结果:
大顶堆
代码:
#include <iostream>
#include <queue>
using namespace std;
struct Student
{
int age;
int score;
bool operator < (const Student& student) const
{
return age < student.age;
}
};
int main()
{
priority_queue<Student,vector<Student> > pq;
// priority_queue<Student,vector<Student>,less<Student>> pq;
// 默认为 less<Student>, 可以不写
printf("=====插入元素的顺序=====\n");
for(int i = 1; i <= 10; i++)
{
printf("%d ", i);
Student* stu = new Student({i,0});
pq.push(*stu);
}
puts("");
printf("=====输出元素的顺序=====\n");
while(pq.size())
{
Student stu = pq.top();
printf("%d ", stu.age);
pq.pop();
}
puts("");
return 0;
}
输出结果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?