C++ sort 函数 以及 priority_queue 的使用

本人在日常使用 C++ 编写程序时,经常有对 sortpriority_queue 的使用感到模棱两可的情况,一忍再忍,忍无可忍,整理出二者常用用法,一方面供自己日后感到困惑时复习,一方面希望帮到一样感到困惑的读者朋友。如有不当之处,敬请体谅。

1. sort 函数的使用

sort 函数的定义:

#include <algorithm> //头文件
sort (first, end, compare);

  1. sort 对 [first, end) 范围内的元素进行排序。
  2. 默认为升序排序(此时不需要传入compare)。
  3. 当需要降序排序时,需要传入比较器 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 所写:

  1. 假定排序完成后的降序是从 左 到 右。
  2. 需要比较的两个数 a , b 在数组的相对位置为 a 在左, b 在右。
  3. return true 则代表二者相对位置正确,不需要改变。
  4. 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 类型。

  1. 假定排序完成后的升序是 从 左 到 右。
  2. *this(当前Student) 和 要比较的Student 的相对位置为 *this 在左, student 在右。
  3. return true: 二者相对位置正确,不需要改变。
  4. 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 类型的函数。

  1. 假定排序完成后的降序是 从 左 到 右。
  2. Student a 和 Student b 的相对位置为 a 在左, b 在右。
  3. return true: 二者相对位置正确,不需要改变。
  4. 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 类型的函数。

  1. 假定排序完成后的降序是 从 左 到 右。
  2. Student a 和 Student b 的相对位置为 a 在左, b 在右。
  3. return true: 二者相对位置正确,不需要改变。
  4. 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>>;

  1. 第一个参数代表堆中数据类型。
  2. 第二个参数代表底层使用的容器,默认为 vector, 可选为deque。
  3. 第三个参数代表堆的类型,大顶堆(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...等往往重载了 > 和 < 运算符。

当使用自定义类型构建堆时,由于堆的大小元素比较,需重载对应的运算符。

  1. 小顶堆,定义时 greater<Type>, 重载 > 运算符。
  2. 大顶堆,定义时 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;
}

输出结果:

posted @   流云散手  阅读(183)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
点击右上角即可分享
微信分享提示