Effective STL理解你的排序操作

排序一直是数据结构中的常用算法,STL提供的排序算法非常丰富,如何有效 使用就值得探讨。在网上没有找到条款31的翻译,于是我自己翻译了。-- Winter

如何进行排序?让我数数有几种方法。

一旦程序员需对容 器元素进行排序,sort算法马上就会出现在他的脑海(可能有些程序员会想到 qsort,但详细阅读条款46后,他们会放弃使用qsort的想法,转而使用sort算法 )。

sort是一个非常优秀的算法,但并当你并不真正需要它的时候,其实 就是一种浪费。有时你并不需要一个完整的排序(简称为全排序)。例如,你现 有一个包含Widget对象(Widget意为“小挂件”)的vector容器,并 且你想把其中质量最好的20个Widget送给你最好的客户,那么你需做的只是找出 这20个质量最好的Widget元素,剩下的并不需关心它们的顺序。这时你需要的是 部分排序(相对于全排序),恰好在算法中就有一个名副其实的部分排序函数函 数:partial_sort:

bool qualityCompare(const Widget& lhs, const Widget& rhs)
{
  // lhs的质量不比rhs的质量差时返回true,否则返回false
}

partial_sort (widgets.begin(),   // 把质量最好的20元素
  widgets.begin() + 20,   // 顺序放入widgets容器中
  widgets.end(),
  qualityCompare);
…  // 使用 widgets...

通过调用partial_sort,容器中开始的20个元素就是你需要的质量最好的20 个Widget,并按顺序排列,质量排第一的就是widgets[0], 紧接着就是widgets [1],依次类推。这样你就可以把质量第一的Widget送给你最好的顾客,质量第 二的Widget就可以送给下一个顾客,很方便吧,更方便的还在后面呢。

如果你只是想把这20个质量最好的Widget礼物送给你最好的20位顾客,而不需要 给他们一一对应,partial_sort在这里就有些显得大材小用了。因为在这里,你 只需要找出这20个元素,而不需要对它们本身进行排序。这时你需要的不是 partial_sort,而是nth_element。

nth_element排序算法只是对一个区 间进行排序,一直到你指定的第n个位置上放上正确的元素为止,也就是说,和 你进行全排序和nth_element排序相比,其共同点就是第n个位置是同一个元素。 当nth_element函数运行后,在全排序中应该在位置n之后的元素不会出现在n的 前面,应该在位置n前面的元素也不会出现在n的后面。听起来有些费解,主要是 我不得不谨慎地使用我的语言来描述nth_element的功能。别着急,呆会儿我会 给你解释为什么,现在先让我们来看看nth_element是如何让质量最好的20个 widget礼物排在vector容器的前面的:

nth_element (widgets.begin(), // 把质量最好的20元素放在
  widgets.begin() + 20,   // widgets容器的前面,
  widgets.end(),  // 但并不关心这20个元素
  qualityCompare);  //本身内部的顺序

你可以看出,调用nth_element函数和调用partial_sort函数在本质上没有区 别,唯一的不同在于partial_sort把前20个元素还进行排列了,而nth_element 并不关系他们内部的顺序。两个算法都实现了同样的功能:把质量最好的20个元 素放在vector容器的开始部分。

这样引起了一个重要的问题:要是质量 一样的元素,排序算法将会如何处理呢?假设有12个元素的质量都为1(最好等 级),15个元素的质量等级为2(质量次之),如果要选择20个最好的Widget, 则先选12个质量为1的元素,然后从15个中选出8个质量为2的元素。到底 nth_element和partial_sort如何从15个中选出8个,依据何在?换句话说,当多 个元素有同样的比较值时,排序算法如何决定谁先谁后?

对于 partial_sort和nth_element算法来说,你无法控制它们,对于比较值相同的元 素它们想怎么排就怎么排(查看条款19,了解两个值相等的定义)。在我们上面 的例子中,面对需要从15个等级为2的元素选出8个增加到top 20中去,他们会任 意选取。这样做也有它的道理:如果你要求得到20个质量最好的Widget,同时有 些Widget的质量又一样,当你得到20个元素至少不比剩下的那些质量差,这已经 达到你的要求,你就不能抱怨什么了。

时间: 2024-10-02 13:56:08

Effective STL理解你的排序操作的相关文章

对象-C++ primer 里面STL容器set的insert操作问题。。。

问题描述 C++ primer 里面STL容器set的insert操作问题... 在C++primer 5th 的13.4节里面有个类的定义是这样的: class Message { friend void swap(Message&, Message&); friend class Folder; public: //folders被隐式初始化为空集合 explicit Message(const string &str=""):contents(str){}

C++ STL中的sort排序算法

问题描述 C++ STL中的sort排序算法 #define _CRT_SECURE_NO_WARNINGS #include"iostream" using namespace std; #include"vector" #include"list" #include"set" #include"algorithm" #include"functional" class teacher

javascript实现对表格元素进行排序操作_javascript技巧

我们在上网中都能看到很多能够排序的,如大小.时间.价格等 现在我们也试一下排序功能: 排序的函数代码:里面含有点击之后排序--还原,和排升序和降序. function sortAge(){ //对年龄进行排序,要先进行获得每一行对象,然后对象对象中的第一个(从0 开始)的大小进行排序 var tabNode = document.getElementById("tabid"); var rows0 = tabNode.rows; var rows1 = []; //现将元素拷贝一份出来

STL学习系列之三:操作list容器

学习完了STL系列之二,自己写了个程序练手!程序采用的还是系列之二文章的架构.学习了STL之一和之二,对于STL的基本原理算有个个基本的了解.其实关于这几种容器,以前也都接触过,不过是在java上,当时学习时也是囫囵吞枣!现在感觉那真是学习之大忌,还是一步一个脚印为好.速度可以放慢点,那要扎实! 注意:程序在vc6下调试通过,对于不清楚如何在vc下运行STL者,可以读STL系列之一. //TjuAiLab //Author:zhangbufeng //Time:2005.8.23 22:00 #

jQuery利用sort对DOM元素进行排序操作_jquery

前言 排序对于我们是再熟悉不过了,在绝大数应用程序中都会有这样一个场景:当我们从服务器端获取一个列表时,在界面上进行渲染,我们可以会依赖于某一个规则来进行排序,当然此时绝大多数会再次与服务器进行交互来进行重新渲染列表到客户端,这样做未尝不可,但是在有些情况下,我们既不需要利用框架也不需要重新生成列表到客户端,明明可以在客户端进行,达到我们的目的,为何要再一次发送请求到服务器呢?下面我们来看看. 话题 我们首先看看在w3c中js的sort方法. <script type="text/java

学习理解Android菜单Menu操作_Android

今天看了pro android 3中menu这一章,对Android的整个menu体系有了进一步的了解,故整理下笔记与大家分享. PS:强烈推荐<Pro Android 3>,是我至今为止看到的最好的一本android书,中文版出到<精通Android 2>. 理解Android的菜单 菜单是许多应用程序不可或缺的一部分,Android中更是如此,所有搭载Android系统的手机甚至都要有一个"Menu"键,由此可见菜单在Android程序中的特殊性.Andro

STL之使用vector排序

应用场景: 在内存中维持一个有序的vector: 1 // VectorSort.cpp : Defines the entry point for the console application. 2 3 #include <iostream> 4 #include <vector> 5 #include <algorithm> 6 7 //先自定义一个结构体 8 struct Test { 9 float member1; 10 std::string member

Effective STL 为包含指针的关联容器指定比较类型

// 为包含指针的关联容器指定比较类型.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <set> #include <string> #include <iostream> using namespace std; struct StringPtrLess: public binary_function<const string*, const string*, bool> {

C++数据结构与算法专题

快速排序算法的C++实现 详解qsort函数的用法 C++求二个数的最大公约数与最小公倍数实例 小览CallStack(调用栈)(三)-用调试器脚本查看调用栈信息 小览call stack(调用栈) (二)--调用约定 小览call stack(调用栈) (一) C++/CLI中栈对象的设计问题 POJ 1694 C++ (排序) 高效实现Josephus算法 利用堆排序实现学生成绩管理 C++双向循环链表的操作与实现 基于Crtpto++的RSA签名算法 自定义函数使用map排序 C++数据结