C++中std::sort/std::stable_sort/std::partial_sort的区别及使用

某些算法会重排容器中元素的顺序,如std::sort。调用sort会重排输入序列中的元素,使之有序,它默认是利用元素类型的<运算符来实现排序的。也可以重载sort的默认排序,即通过sort的第三个参数,此参数是一个谓词(predicate)。

        谓词是一个可调用的表达式,其返回结果是一个能用作条件的值,即返回一个bool类型的值。标准库算法所使用的谓词分为两类:一元谓词(unary predicate,只接受单一参数)和二元谓词(binary predicate,有两个参数)。接受谓词参数的算法对输入序列中的元素调用谓词。因此,元素类型必须能转换为谓词的参数类型。

        接受一个二元谓词参数的sort版本用这个谓词代替<来比较元素。

        std::sort:对给定区间所有元素进行排序。

        std::stable_sort:对给定区间所有元素进行稳定排序,稳定排序算法能够维持相等元素的原有顺序。

        std::partial_sort:对给定区间所有元素进行部分排序。

        当容器中的元素是一些标准类型(如int、string)时,可以直接使用函数模板。但其元素是自定义类型或者需要按照其它方式排序时,需要自己来实现,有两种方法:一种是自己写比较函数,另一种是重载类型操作符”<”。std::sort/std::stable_sort/std::partial_sort中最后一个参数可以是函数指针类型或函数对象类型。

        std::sort采用类似快速排序算法,复杂度为N*log2(N);std::stable_sort采用类似归并排序,复杂度为N*log2(N);std::partial_sort采用类似堆排序,复杂度为N*log(M)。但是在cplusplus中并没有说明每种sort采用的是具体哪种排序算法。

        std::sort:Sort elements in range, Sorts the elements in the range [first,last) into ascending order. The elements are compared using operator< for the first version, and comp for the second. Equivalent elements are not guaranteed to keep their original relative order (see stable_sort).

        std::stable_sort: Sort elements preserving order of equivalents. Sorts the elements in the range[first,last) into ascending order, like sort, but stable_sort preserves the relative order of the elements with equivalent values.

        std::partial_sort:Partially sort elements in range. Rearranges the elements in the range [first,last), in such a way that the elements before middle are the smallest elements in the entire range and are sorted in ascending order, while the remaining elements are left without any specific order.

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

#include "sort1.hpp"
#include <iostream>
#include <algorithm> // std::sort
#include <functional> // std::greater
#include <vector>
#include <array>
#include <string>

///
// reference: http://www.cplusplus.com/reference/algorithm/sort/
static bool myfunction(int i, int j) { return (i < j); }

static struct myclass {
	bool operator() (int i, int j) { return (i < j); }
} myobject;

int test_sort_1()
{
	int myints[] { 32, 71, 12, 45, 26, 80, 53, 33 };
	std::vector<int> myvector(myints, myints + 8);               // 32 71 12 45 26 80 53 33

	// using default comparison (operator <):
	std::sort(myvector.begin(), myvector.begin() + 4);           //(12 32 45 71)26 80 53 33

	// using function as comp
	std::sort(myvector.begin() + 4, myvector.end(), myfunction); // 12 32 45 71(26 33 53 80)

	// using object as comp
	std::sort(myvector.begin(), myvector.end(), myobject);     //(12 26 32 33 45 53 71 80)

	// print out content:
	std::cout << "myvector contains:";
	for (std::vector<int>::iterator it = myvector.begin(); it != myvector.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';

	myvector.assign(myints, myints + 8);
	std::sort(myvector.begin(), myvector.end(), std::greater<int>()); // descending is to use std::greater()
	std::cout << "myvector contains:";
	for (std::vector<int>::iterator it = myvector.begin(); it != myvector.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';

	// use std::sort to sort an array in C++11: std::begin/std::end
	std::sort(std::begin(myints), std::end(myints));
	for (int i = 0; i < 8; ++i) {
		std::cout << " " << myints[i];
	}
	std::cout << "\n";

	return 0;
}

/
// reference: https://www.codeproject.com/Articles/38381/STL-Sort-Comparison-Function
class Person_sort4 {
public:
	// default constructor
	Person_sort4() : age(0) {}
	Person_sort4(int age, std::string name) {
		this->age = age; this->name = name;
	}
	bool operator<(const Person_sort4& rhs) { // define a member < operator for the Person class
		return this->age < rhs.age;
	}

	int age;
	std::string name;
};

int test_sort_4()
{
	std::vector<Person_sort4> vecPerson;
	vecPerson.push_back(Person_sort4(24, "Calvin"));
	vecPerson.push_back(Person_sort4(30, "Benny"));
	vecPerson.push_back(Person_sort4(28, "Alison"));

	std::sort(vecPerson.begin(), vecPerson.end());

	for (size_t i = 0; i<vecPerson.size(); ++i)
		std::cout << vecPerson[i].age << ", " << vecPerson[i].name << std::endl;

	return 0;
}

/
// reference: http://www.cplusplus.com/articles/NhA0RXSz/
struct Person_sort {
	// Left out making a constructor for simplicity's sake.
	std::string name;
	int age;
	std::string favoriteColor;
};

// Sort Container by name function
static bool sortByName(const Person_sort &lhs, const Person_sort &rhs) { return lhs.name < rhs.name; }

// Sort Container by age function
static bool sortByAge(const Person_sort &lhs, const Person_sort &rhs) { return lhs.age < rhs.age; }

// Sort Container by favorite color
// We can just sort alphabetically and then it will group the color together.
static bool sortByColor(const Person_sort &lhs, const Person_sort &rhs) { return lhs.favoriteColor < rhs.favoriteColor; }

// A global const variable to hold how many people to ask for input for.
const unsigned numberOfPeople = 2;

int test_sort_2()
{
	using std::vector;
	using std::cout;
	using std::cin;
	using std::endl;
	using std::sort;
	using std::string;

	// Make a vector that holds 5 blank Person_sort Objects
	vector<Person_sort> people { { "Tom", 23, "Red" }, {"Jim", 11, "Green"} };

	// This will ask for user input to populate the container
	// with 5 different indivuals.
	//for (vector<Person_sort>::size_type i = 0; i != numberOfPeople; ++i) {
	//	cout << "Person_sort #" << i + 1 << " name: ";
	//	cin >> people[i].name;

	//	cout << "Person_sort #" << i + 1 << " age: ";
	//	cin >> people[i].age;

	//	cout << "Person_sort #" << i + 1 << " favorite color: ";
	//	cin >> people[i].favoriteColor;
	//}
	//cout << "\n\n";

	// Sort by name
	sort(people.begin(), people.end(), sortByName);
	for (Person_sort &n : people)
		cout << n.name << " ";
	cout << endl;

	// Sory by age
	sort(people.begin(), people.end(), sortByAge);
	for (Person_sort &n : people)
		cout << n.age << " ";
	cout << endl;

	// Sort by color
	sort(people.begin(), people.end(), sortByColor);
	for (Person_sort &n : people)
		cout << n.favoriteColor << " ";
	cout << endl;

	return 0;
}

/
// reference: http://en.cppreference.com/w/cpp/algorithm/sort
int test_sort_3()
{
	std::array<int, 10> s = { 5, 7, 4, 2, 8, 6, 1, 9, 0, 3 };

	// sort using the default operator<
	std::sort(s.begin(), s.end());
	for (auto a : s) {
		std::cout << a << " ";
	}
	std::cout << '\n';

	// sort using a standard library compare function object
	std::sort(s.begin(), s.end(), std::greater<int>());
	for (auto a : s) {
		std::cout << a << " ";
	}
	std::cout << '\n';

	// sort using a custom function object
	struct {
		bool operator()(int a, int b) const {
			return a < b;
		}
	} customLess;
	std::sort(s.begin(), s.end(), customLess);
	for (auto a : s) {
		std::cout << a << " ";
	}
	std::cout << '\n';

	// sort using a lambda expression 
	std::sort(s.begin(), s.end(), [](int a, int b) {
		return b < a;
	});
	for (auto a : s) {
		std::cout << a << " ";
	}
	std::cout << '\n';

	return 0;
}

/
// reference: http://www.cplusplus.com/reference/algorithm/stable_sort/
static bool compare_as_ints(double i, double j)
{
	return (int(i)<int(j));
}

int test_stable_sort_1()
{
	double mydoubles[] { 3.14, 1.41, 2.72, 4.67, 1.73, 1.32, 1.62, 2.58 };

	std::vector<double> myvector;
	myvector.assign(mydoubles, mydoubles + 8);

	std::cout << "using default comparison:";
	std::stable_sort(myvector.begin(), myvector.end());
	for (std::vector<double>::iterator it = myvector.begin(); it != myvector.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';

	myvector.assign(mydoubles, mydoubles + 8);

	std::cout << "using 'compare_as_ints' :";
	std::stable_sort(myvector.begin(), myvector.end(), compare_as_ints);
	for (std::vector<double>::iterator it = myvector.begin(); it != myvector.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';

	return 0;
}

/
// reference: http://en.cppreference.com/w/cpp/algorithm/stable_sort
struct Employee_sort {
	Employee_sort(int age, std::string name) : age(age), name(name) { }
	int age;
	std::string name;  // Does not particpate in comparisons
};

static bool operator<(const Employee_sort &lhs, const Employee_sort &rhs)
{
	return lhs.age < rhs.age;
}

int test_stable_sort_2()
{
	std::vector<Employee_sort> v = {
		Employee_sort(108, "Zaphod"),
		Employee_sort(32, "Arthur"),
		Employee_sort(108, "Ford"),
	};

	std::stable_sort(v.begin(), v.end());

	for (const Employee_sort &e : v) {
		std::cout << e.age << ", " << e.name << '\n';
	}

	return 0;
}


// reference: http://www.cplusplus.com/reference/algorithm/partial_sort/
int test_partial_sort_1()
{
	int myints[] { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
	std::vector<int> myvector(myints, myints + 9);

	// using default comparison (operator <):
	std::partial_sort(myvector.begin(), myvector.begin() + 5, myvector.end());

	// using function as comp
	std::partial_sort(myvector.begin(), myvector.begin() + 5, myvector.end(), myfunction);

	// print out content:
	std::cout << "myvector contains:";
	for (std::vector<int>::iterator it = myvector.begin(); it != myvector.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';

	return 0;
}

GitHubhttps://github.com/fengbingchun/Messy_Test

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言没有STL库,也没有类似于C++std::partial_sort的内置函数。不过,我们可以使用快速排序算法来实现类似的功能。 快速排序算法的基本思想是选择一个基准元素,将数组分成两部分,一部分小于等于基准元素,另一部分大于基准元素。然后递归地对两部分分别进行快速排序,最终得到一个有序数组。 实现std::partial_sort的步骤如下: 1. 取数组前k个元素作为基准元素,对其进行快速排序。 2. 遍历数组第k个元素到最后一个元素,并将其与基准元素进行比较,如果小于等于基准元素,则将其插入到前k个元素,并对前k个元素进行快速排序。 3. 最终得到前k个元素是数组最小的k个元素,但它们并不一定是有序的。可以使用任意排序算法对其进行排序。 下面是一个示例代码: ```c #include <stdio.h> void quick_sort(int arr[], int left, int right) { if (left >= right) return; int i = left, j = right; int pivot = arr[left]; while (i < j) { while (i < j && arr[j] > pivot) j--; if (i < j) arr[i++] = arr[j]; while (i < j && arr[i] <= pivot) i++; if (i < j) arr[j--] = arr[i]; } arr[i] = pivot; quick_sort(arr, left, i - 1); quick_sort(arr, i + 1, right); } void partial_sort(int arr[], int n, int k) { quick_sort(arr, 0, k - 1); for (int i = k; i < n; i++) { if (arr[i] <= arr[k - 1]) { arr[k - 1] = arr[i]; quick_sort(arr, 0, k - 1); } } quick_sort(arr, 0, k - 1); } int main() { int arr[] = {1, 3, 2, 5, 4}; int n = sizeof(arr) / sizeof(arr[0]); int k = 3; partial_sort(arr, n, k); for (int i = 0; i < k; i++) { printf("%d ", arr[i]); } printf("\n"); return 0; } ``` 该代码实现了类似于std::partial_sort的功能,输出结果为1 2 3,即数组最小的3个元素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值