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

2023-11-19

某些算法会重排容器中元素的顺序,如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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++中std::sort/std::stable_sort/std::partial_sort的区别及使用 的相关文章

  • C++中static_cast/const_cast/dynamic_cast/reinterpret_cast的区别和使用

    C风格的强制转换较简单 如将float a转换为int b 则可以这样 b int a 或者b int a C 类型转换分为隐式类型转换和显示类型转换 隐式类型转换又称为标准转换 包括以下几种情况 1 算术转换 在混合类型的算术表达式中 最
  • C和C++安全编码笔记:整数安全

    5 1 整数安全导论 整数由包括0的自然数 0 1 2 3 和非零自然数的负数 1 2 3 构成 5 2 整数数据类型 整数类型提供了整数数学集合的一个有限子集的模型 一个具有整数类型的对象的值是附着在这个对象上的数学值 一个具有整数类型的
  • C++/C++11中头文件algorithm的使用

  • C++中namespace detail或namespace internal的使用

    在很多开源代码中偶尔会使用名字为 detail 或 internal 的命名空间 如OpenCV的modules目录中 有些文件中使用了namespace detail 有些文件中使用了namespace internal 名为detail
  • C和C++安全编码笔记:指针诡计

    指针诡计 pointer subterfuge 是通过修改指针值来利用程序漏洞的方法的统称 可以通过覆盖函数指针将程序的控制权转移到攻击者提供的外壳代码 shellcode 当程序通过函数指针执行一个函数调用时 攻击者提供的代码将会取代原本
  • C++11中std::function的使用

    类模版std function是一种通用 多态的函数封装 std function的实例可以对任何可以调用的目标实体进行存储 复制 和调用操作 这些目标实体包括普通函数 Lambda表达式 函数指针 以及其它函数对象等 通过std func
  • C++11中头文件atomic的使用

    原子库为细粒度的原子操作提供组件 允许无锁并发编程 涉及同一对象的每个原子操作 相对于任何其他原子操作是不可分的 原子对象不具有数据竞争 data race 原子类型对象的主要特点就是从不同线程访问不会导致数据竞争 因此从不同线程访问某个原
  • C和C++安全编码笔记:文件I/O

    C和C 程序通常会对文件进行读写 并将此作为它们正常操作的一部分 不计其数的漏洞正是由这些程序与文件系统 其操作由底层操作系统定义 交互方式的不规则性而产生的 这些漏洞最常由文件的识别问题 特权管理不善 以及竞争条件导致 8 1 文件I O
  • log库spdlog简介及使用

    spdlog是一个开源的 快速的 仅有头文件的C 11 日志库 code地址在 https github com gabime spdlog 目前最新的发布版本为0 14 0 它提供了向流 标准输出 文件 系统日志 调试器等目标输出日志的能
  • Effective C++改善程序与设计的55个具体做法笔记

    Scott Meyers大师Effective三部曲 Effective C More Effective C Effective STL 这三本书出版已很多年 后来又出版了Effective Modern C More Effective
  • 提高C++性能的编程技术笔记:引用计数+测试代码

    引用计数 reference counting 基本思想是将销毁对象的职责从客户端代码转移到对象本身 对象跟踪记录自身当前被引用的数目 在引用计数达到零时自行销毁 换句话说 对象不再被使用时自行销毁 引用计数和执行速度之间的关系是与上下文紧
  • 内存检测工具Dr. Memory的使用

    Dr Memory是一个内存调试工具 它是一个开源免费的内存检测工具 它能够及时发现内存相关的编程错误 比如未初始化访问 内存非法访问 数组越界读 写 以及内存泄露等 它可以在Linux Windows Mac OS和Android操作系统
  • json11库的使用

    JSON JavaScript Object Notation 是一种轻量级的文本数据交换格式 易于让人阅读 同时也易于机器解析和生成 尽管JSON是Javascript的一个子集 但JSON是独立于语言的文本格式 并且采用了类似于C语言家
  • 概率论中伯努利分布(bernoulli distribution)介绍及C++11中std::bernoulli_distribution的使用

    Bernoulli分布 Bernoulli distribution 是单个二值随机变量的分布 它由单个参数 0 1 给出了随机变量等于1的概率 它具有如下的一些性质 P x 1 P x 0 1 P x x x 1 1 x Ex x Var
  • C/C++中#pragma once的使用

    在C C 中 为了避免同一个文件被include多次 有两种方式 一种是 ifndef方式 一种是 pragma once方式 在头文件的最开始加入 ifndef SOME UNIQUE NAME HERE define SOME UNIQ
  • C++11中thread_local的使用

    C 11中的thread local是C 存储期的一种 属于线程存储期 存储期定义C 程序中变量 函数的范围 可见性 和生命周期 C 程序中可用的存储期包括auto register static extern mutable和thread
  • C++11中std::shared_future的使用

    C 11中的std shared future是个模板类 与std future类似 std shared future提供了一种访问异步操作结果的机制 不同于std future std shared future允许多个线程等待同一个共
  • 开源库jemalloc简介

    jemalloc是通用的malloc 3 实现 它强调避免碎片和可扩展的并发支持 它的源码位于https github com jemalloc jemalloc 最新稳定版本为5 2 1 glibc的内存分配算法是基于dlmalloc实现
  • Linux下getopt函数的使用

    getopt为解析命令行参数函数 它是Linux C库函数 使用此函数需要包含系统头文件unistd h getopt函数声明如下 int getopt int argc char const argv const char optstri
  • 提高C++性能的编程技术笔记:单线程内存池+测试代码

    频繁地分配和回收内存会严重地降低程序的性能 性能降低的原因在于默认的内存管理是通用的 应用程序可能会以某种特定的方式使用内存 并且为不需要的功能付出性能上的代价 通过开发专用的内存管理器可以解决这个问题 对专用内存管理器的设计可以从多个角度

随机推荐

  • LINUX上wireshark无权限问题

    1 查找dumpcap目录 sudo find name dumpcap 2 增加wireshark组 sudo groupadd wireshark 3 将dumpcap目录权限给于wireshark组 并给于相关权限 sudo chgr
  • border-radius使用详解

    我在使用这个属性的时候 一般都是用在给div或者button加上一点圆角弧度 显得好看一点 或者用来画一个圆形div 用的稍微高级一点的 也就是用来画了一个右半圆来做为侧边栏的展开 收缩按钮 一 border radius使用 border
  • Java线程的6种状态及切换(透彻讲解)

    Java中线程的状态分为6种 1 初始 NEW 新创建了一个线程对象 但还没有调用start 方法 2 运行 RUNNABLE Java线程中将就绪 ready 和运行中 running 两种状态笼统的称为 运行 线程对象创建后 其他线程
  • 二进制文件反序列化错误

    二进制文件反序列化 出现错误 SerializationException was unhandled The ObjectManager found an invalid number of fixups This usually ind
  • 两小时快速入门 TypeScript 基础(一)工作流、基本类型、高级类型

    个人简介 个人主页 前端杂货铺 学习方向 主攻前端方向 也会涉及到服务端 Node js 等 个人状态 2023届本科毕业生 已拿多个前端 offer 秋招 未来打算 为中国的工业软件事业效力 n 年 推荐学习 前端面试宝典 Vue2 Vu
  • Splunk 优化之加速报表 Accelerate reports

    1 背景 有些客户的数据比较大 这个时候就会用到 报表的加速功能 Accelerate reports If your report has a large number of events and is slow to complete
  • 蓝桥杯-分巧克力(二分搜索)

    历届试题 分巧克力 时间限制 1 0s 内存限制 256 0MB 问题描述 儿童节那天有K位小朋友到小明家做客 小明拿出了珍藏的巧克力招待小朋友们 小明一共有N块巧克力 其中第i块是Hi x Wi的方格组成的长方形 为了公平起见 小明需要从
  • 程序无法启动ALL_BUILD 拒绝访问

    用cmake编译完opencv3 0后 发现编译没有问题 但尝试调试的时候报错 无法启动 ALL BUILD拒绝访问 调了很久才解决 方法是 卸载所有无关工程 只保留一个你需要的工程 这时候ZERO CHECK以及ALL BUILD都没有必
  • 什么是数字货币、数字金融 和区块链?

    从金融视角来说 区块链和数字货币 其实就是新一代的数字金融体系 数字金融体系 就是建立在区块链数字货币的金融基础设施上的 站在企业的角度 怎么来理解数字经济 我们知道工业经济驱动因素是化石燃料 数字经济驱动因素是数据 那么数据怎么去驱动一个
  • JAVA实习生刚进入公司一般会被安排做什么样的工作?

    新人进公司首先给你配置个人有邮箱和ip clone代码让你熟悉大概有一周左右 再在此之间 可能会有你的同事或者组长来给你大致讲一下项目的模块 架构 数据库 有的 公司让你看 不懂的让你去问他 针对于刚毕业的 还没有相关经验的可能会有所不同
  • 华为服务器bmc怎么传文件,华为服务器bmc配置

    华为服务器bmc配置 内容精选 换一换 通过华为云创建的ECS服务器默认使用华为云提供的内网DNS进行解析 内网DNS不影响ECS服务器对公网域名的访问 同时 还可以不经Internet 直接通过内网DNS访问其他云上服务内部地址 如OBS
  • 如何修改cmd控制台默认编码为utf-8,正确显示汉字

    首先我们打开在运行输入框等方式打开cmd窗口后 在窗口顶部右击选择属性 选中选项后会看到默认编码为gbk 然后我们在默认窗口路径内 输入chcp命令后回车 会输出图中的结果 936就表示gbk编码 然后在窗口中输入chcp 65001 65
  • ECharts 设置折线颜色和小圆点颜色

    ECharts 设置折线颜色只需要设置lineStyle的color即可 设置小圆点颜色只需要设置itemStyle的颜色即可 series name seriesName type line itemStyle normal color
  • Spark性能优化指南——基础篇

    前言 在大数据计算领域 Spark已经成为了越来越流行 越来越受欢迎的计算平台之一 Spark的功能涵盖了大数据领域的离线批处理 SQL类处理 流式 实时计算 机器学习 图计算等各种不同类型的计算操作 应用范围与前景非常广泛 在美团 大众点
  • 高德地图——步行导航

    高德地图 步行导航 插件 plugin AMap Walking 步行导航和驾驶导航几乎是一样的 唯一的不同便是导入的插件不同 步行导航的全程都是蓝色的 而驾驶导航线会有红色拥堵 绿色通畅的颜色
  • 实现java导出文件弹出下载框让用户选择路径

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 在实现导出文件时 弹出下载框主要是设置成文件流 stream类型的response 浏览器就会识别 然后弹出下载框让用户选择保存路径 这里总结三个方式 web struts
  • c# asp.net 如何在js文件中使用服务器变量,asp.net中JS,CS 调用后台变量的值多种方法...

    本文章介绍了关于asp net中JS CS 调用后台变量的值多种方法 有需了解的朋友可以参考一下 1 后台 Publicstringstr 123 最好为Public类型 直接在AspX前台页面HTML代码中要放的位置写入如下代码 2 用J
  • 解决${}EL表达式不起作用,无法获取数据,页面显示内容出错

    问题 EL表达式无法获取数据 解决办法 在jsp页面加入 这句话表示 可以使用EL 表达式 效果
  • html标签中src=“图片路径”,怎么用变量替换路径

    div style background image none bg0 gif bg5 gif div
  • C++中std::sort/std::stable_sort/std::partial_sort的区别及使用

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