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++/C++11中头文件algorithm的使用

  • 在Ubuntu 18.04上支持C++17的std::filesystem的方法

    在Ubuntu 18 04上通过命令sudo apt install gcc g 安装的gcc g 版本为7 5 此版本并不直接支持filesystem 如下图所示 Ubuntu 18 04上的g 7 5支持experimental的fil
  • C++11中std::future的使用

    C 11中的std future是一个模板类 std future提供了一种用于访问异步操作结果的机制 std future所引用的共享状态不能与任何其它异步返回的对象共享 与std shared future相反 std future r
  • C和C++安全编码笔记:指针诡计

    指针诡计 pointer subterfuge 是通过修改指针值来利用程序漏洞的方法的统称 可以通过覆盖函数指针将程序的控制权转移到攻击者提供的外壳代码 shellcode 当程序通过函数指针执行一个函数调用时 攻击者提供的代码将会取代原本
  • 程序员的自我修养--链接、装载与库笔记:可执行文件的装载与进程

    可执行文件只有装载到内存以后才能被CPU执行 1 进程虚拟地址空间 程序和进程有什么区别 程序 或者狭义上讲可执行文件 是一个静态的概念 它就是一些预先编译好的指令和数据集合的一个文件 进程则是一个动态的概念 它是程序运行时的一个过程 很多
  • C++11中头文件atomic的使用

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

    引用 reference 是一种复合类型 compound type 引用为对象起了另外一个名字 引用类型引用 refer to 另外一种类型 通过将声明符写成 d的形式来定义引用类型 其中d是声明的变量名 一 一般引用 一般在初始化变量时
  • 提高C++性能的编程技术笔记:多线程内存池+测试代码

    为了使多个线程并发地分配和释放内存 必须在分配器方法中添加互斥锁 全局内存管理器 通过new 和delete 实现 是通用的 因此它的开销也非常大 因为单线程内存管理器要比多线程内存管理器快的多 所以如果要分配的大多数内存块限于单线程中使用
  • C和C++安全编码笔记:并发

    并发是一种系统属性 它是指系统中几个计算同时执行 并可能彼此交互 一个并发程序通常使用顺序线程和 或 进程的一些组合来执行计算 其中每个线程和进程执行可以在逻辑上并行执行的计算 这些进程和 或 线程可以在单处理器系统上使用分时抢占式的方式
  • Effective C++改善程序与设计的55个具体做法笔记

    Scott Meyers大师Effective三部曲 Effective C More Effective C Effective STL 这三本书出版已很多年 后来又出版了Effective Modern C More Effective
  • 程序员的自我修养--链接、装载与库笔记:Linux共享库的组织

    共享库 Shared Library 概念 其实从文件结构上来讲 共享库和共享对象没什么区别 Linux下的共享库就是普通的ELF共享对象 由于共享对象可以被各个程序之间共享 所以它也就成为了库的很好的存在形式 很多库的开发者都以共享对象的
  • json11库的使用

    JSON JavaScript Object Notation 是一种轻量级的文本数据交换格式 易于让人阅读 同时也易于机器解析和生成 尽管JSON是Javascript的一个子集 但JSON是独立于语言的文本格式 并且采用了类似于C语言家
  • C++14中返回类型推导的使用

    使用C 14中的auto返回类型 编译器将尝试自动推导 deduce 返回类型 namespace int xx 1 auto f return xx return type is int const auto f3 return xx r
  • C++中插件使用举例

    插件并不是在构建时链接的 而是在运行时发现并加载的 因此 用户可以利用你定义好的插件API来编写自己的插件 这样他们就能以指定方式扩展API的功能 插件库是一个动态库 它可以独立于核心API编译 在运行时根据需要显示加载 不过插件也可以使用
  • C++中typeid的使用

    RTTI Run TimeType Information 运行时类型信息 它提供了运行时确定对象类型的方法 在C 中 为了支持RTTI提供了两个操作符 dynamic cast和typeid The typeid operator pro
  • CSV文件简介及C++实现

    逗号分隔值 Comma Separated Values CSV 有时也称为字符分隔值 因为分隔字符也可以不是逗号 其文件以纯文本形式存储表格数据 数字和文本 纯文本意味着该文件是一个字符序列 不含必须象二进制数字那样被解读的数据 CSV文
  • 程序员的自我修养--链接、装载与库笔记:目标文件里有什么

    编译器编译源代码后生成的文件叫做目标文件 目标文件从结构上讲 它是已经编译后的可执行文件格式 只是还没有经过链接的过程 其中可能有些符号或有些地址还没有被调整 其实它本身就是按照可执行文件格式存储的 只是跟真正的可执行文件在结构上稍有不同
  • C++中nothrow的介绍及使用

    在C中 使用malloc等分配内存的函数时 一定要检查其返回值是否为 空指针 并以此作为检查内存操作是否成功的依据 这种Test for NULL代码形式是一种良好的编程习惯 也是编写可靠程序所必需的 在C 中new在申请内存失败时默认会抛
  • C++11中thread_local的使用

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

    getopt为解析命令行参数函数 它是Linux C库函数 使用此函数需要包含系统头文件unistd h getopt函数声明如下 int getopt int argc char const argv const char optstri

随机推荐

  • 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