sort自定义排序规则的static函数

本文探讨了C++标准库中的sort函数如何使用自定义比较函数,并强调了当比较函数作为类成员时必须声明为静态成员的原因。通过示例展示了在LeetCode等平台中如何正确实现这一功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

sort函数对系统类型默认升序排列,当我们想降序排列或者对自定义数据类型排序时需要手写排序函数cmp,具体语句为sort(a.begin(),a.end(),cmp)

在做leetcode501题目时,发现自定义sort排序函数报错:error: reference to non-static member function must be called;英文的大致意思是:sort调用函数必须是static类型的。
所以这里牵扯出一个小知识点:sort中的比较函数compare要声明为静态成员函数或全局函数,不能作为普通成员函数,否则会报错

在平常使用中,我们一般都是声明为全局函数,所以不会报错

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
bool cmp(const int& a, const int& b)
{
	return a > b; //从大到小排序
}
int main()
{
	int a[10] = {2, 3, 30, 305, 32, 334, 40, 47, 5, 1};
	vector<int> nums(a, a + 10);
	sort(nums.begin(), nums.end(), cmp);
	for(auto x : nums)
		cout << x;
	cout << endl;
	system("pause");
	return 0;
}

但在leetcode的类模板中,cmp不能作为普通成员函数调用,要声明成静态成员函数

class Solution {
private:

void searchBST(TreeNode* cur, unordered_map<int, int>& map) { // 前序遍历
    if (cur == NULL) return ;
    map[cur->val]++; // 统计元素频率
    searchBST(cur->left, map);
    searchBST(cur->right, map);
    return ;
}


//声明成静态成员函数
bool static cmp (const pair<int, int>& a, const pair<int, int>& b) {
    return a.second > b.second;
}


public:
    vector<int> findMode(TreeNode* root) {
        unordered_map<int, int> map; // key:元素,value:出现频率
        vector<int> result;
        if (root == NULL) return result;
        searchBST(root, map);
        vector<pair<int, int>> vec(map.begin(), map.end());
        sort(vec.begin(), vec.end(), cmp); // 给频率排个序
        result.push_back(vec[0].first);
        for (int i = 1; i < vec.size(); i++) { 
            // 取最高的放到result数组中
            if (vec[i].second == vec[0].second) result.push_back(vec[i].first);
            else break;
        }
        return result;
    }
};

因为:非静态成员函数是依赖于具体对象的,而std::sort这类函数是全局的,因此无法再sort中调用非静态成员函数。
静态成员函数或者全局函数是不依赖于具体对象的, 可以独立访问,无须创建任何对象实例就可以访问。同时静态成员函数不可以调用类的非静态成员。

<think>好的,我现在需要帮助用户了解如何在Java中自定义sort排序函数,特别是实现Comparator接口的示例。首先,我得回忆一下Java中的排序机制。用户提到了Comparator和Comparable,这两个接口的区别是关键。Comparable是让自身实现比较,而Comparator是外部比较器,可以在不修改的情况下定义多种排序方式。用户的问题主要集中在Comparator上,所以应该详细讲解如何实现它。 接下来,用户需要一个示例。我需要构造一个简单的场景,比如一个学生,然后根据年龄或姓名排序。这样用户容易理解。步骤应该包括:创建自定义、实现Comparator接口、重写compare方法,然后使用Collections.sort或list.sort进行排序。 还要注意代码的格式和注释,确保清晰。比如,展示匿名内部和Lambda表达式两种方式,这样用户知道不同的实现方法。同时,要提到Comparator的链式调用,比如thenComparing,这对多条件排序很有用。 然后,检查是否有遗漏点。比如,比较的返回值规则:负数、零、正数分别代表小于、等于、大于。需要明确说明,避免用户混淆。此外,提醒用户区分Comparable和Comparator的应用场景,虽然用户主要问Comparator,但简要对比有助于加深理解。 用户提供的引用资料中提到Arrays.sort和Collections.sort,以及Comparator接口的compare方法,这些都需要在回答中引用。例如,在代码示例部分,可以引用[^2]和[^4],说明如何实现自定义排序规则。 最后,生成相关问题,确保符合用户的要求。问题可以涉及不同数据型的排序、降序排列、多条件排序等,帮助用户进一步探索。同时,确认所有数学表达式和公式的格式是否正确,虽然这个问题可能不涉及太多数学内容,但如果有变量名之的,需要用$符号包裹。 总结步骤:解释Comparator的作用,给出学生的例子,展示两种实现方式(匿名和Lambda),说明compare方法的返回值,演示如何使用sort方法,引用相关资料,最后生成相关问题。这样结构清晰,逐步引导用户理解和应用自定义排序方法。</think>在 Java 中自定义排序可通过实现 `Comparator` 接口完成。以下是具体实现步骤和示例: --- ### 一、实现 Comparator 接口的步骤 1. **定义需要排序的** 例如创建一个 `Student` : ```java public class Student { private String name; private int age; // 构造方法、getter/setter 省略 } ``` 2. **实现 Comparator 接口** 通过匿名内部或 Lambda 表达式定义排序规则: ```java // 匿名内部方式 Comparator<Student> ageComparator = new Comparator<>() { @Override public int compare(Student s1, Student s2) { return Integer.compare(s1.getAge(), s2.getAge()); // 按年龄升序 } }; // Lambda 表达式方式(Java 8+) Comparator<Student> nameComparator = (s1, s2) -> s1.getName().compareTo(s2.getName()); ``` 3. **应用排序** 使用 `Collections.sort()` 或 `List.sort()`: ```java List<Student> students = new ArrayList<>(); // 添加学生对象... // 按年龄排序 students.sort(ageComparator); // 按姓名排序 Collections.sort(students, nameComparator); ``` --- ### 二、完整代码示例 ```java import java.util.*; public class CustomSortDemo { public static void main(String[] args) { List<Student> students = Arrays.asList( new Student("Alice", 20), new Student("Bob", 18), new Student("Charlie", 22) ); // 按年龄升序排序 students.sort(new Comparator<Student>() { @Override public int compare(Student s1, Student s2) { return Integer.compare(s1.getAge(), s2.getAge()); } }); // 按姓名降序(Lambda 实现) students.sort((s1, s2) -> s2.getName().compareTo(s1.getName())); // 输出结果 students.forEach(s -> System.out.println(s.getName() + ": " + s.getAge())); } } class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } } ``` --- ### 三、核心规则说明 1. **`compare()` 返回值逻辑** - 返回负数:`o1` 排在 `o2` 前面 - 返回正数:`o1` 排在 `o2` 后面 - 返回 0:视为相等 2. **多条件排序** 使用 `thenComparing()` 实现链式排序: ```java Comparator<Student> complexComparator = Comparator .comparingInt(Student::getAge) // 先按年龄升序 .thenComparing(Student::getName); // 再按姓名升序 ``` --- ### 四、Comparable vs Comparator - **Comparable**:对象自身实现比较逻辑(需修改)[^3] - **Comparator**:外部定义灵活比较规则(无需修改)[^2] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值