这里存放的是笔者在学习算法和数据结构时相关的学习笔记,记录了笔者通过网络和书籍资料中学习到的知识点和技巧,在供自己学习和反思的同时为有需要的人提供一定的思路和帮助。

  从排序开始

  基本的排序算法包括冒泡排序、插入排序、选择排序和快速排序的算法原理从基础的数据结构教程中即可学习,不在本文的讨论范围之内。这里主要介绍的是在算法设计程序中可以直接利用的排序工具。C/C++ 为使用者提供了标准的快速排序算法以供使用,在实际的算法设计中,使用者可以通过简单的函数调用实现排序功能。具体而言,C 实现了 qsort 函数提供排序功能,而 C++ 则提供 sort 供用户使用。

  sort

  sort 为 C++ 标准模版库实现的提供排序功能的函数模版。在使用时,需要包含头文件 <algorithm> ,并声明 C++ 的标准命名空间 std.  

    #include <algorithm>
using namespace std; //使用 sort 需要包含对应的头文件,并使用命名空间 std

  在实际使用 sort 时,主要通过以下两种参数形式来调用 sort 提供的排序功能。sort 实现的快速排序算法的时间复杂度为O(nlogn).

    sort( start , end )         //对 start 至 end 之间的数据排序,其中,处理的数据包括 start 而不包括 end
sort( start , end , cmp)      //使用自定义的排序规则 cmp 对 start 和 end 之间的数据排序

  其中 start 为待排序的数据的第一个元素的起始地址,end 为待排序的数据的最后一个元素的地址的下一个地址( 注意不是尾元素的地址 )。当使用第一种形式时,默认对待排序的元素进行升序排列。

  例: int a[5] 为一个包含有 5 个 int 数据的数组,调用 sort( a , a + 5 ) 对数组 a 进行排序,则数组 a 中的元素将按照升序排列。这里注意,排序数据的第一个元素的地址为 a ,最后一个元素的地址为 a + 4 ,调用 sort 时 end 参数应该为最后一个元素地址的下一位也就是 a + 5.

  sort 的第一种调用方式可以对 c++ 支持的基础数据类型进行排序。使用者也可以通过第二种形式来调用 sort ,通过 cmp 来指定排序的规则,从而对自定义的数据结构体进行排序。cmp 函数使用两个待排序的数据作为参数,并返回一个 bool 类型的值,当 返回值为 true 时,则将作为参数的第二个数据排在第一个数据前面。cmp 的大致结构如下所示。

    bool cmp( type a , type b )
{
判断规则 //当 cmp 函数返回 true 时,则将数据 b 排在数据 a 的前面
}

  例:对于一个自定义的学生的数据结构类型,其为一个包含有准考证、姓名和分数信息,要求对包含有学生数据的数组进行排序,使得学生按分数从高到低,分数一致时按准考证号从低到高排序。学生结构的定义如下所示。

    typedef struct{
int sno;
int score;
char name[];
}Student;

  则根据上述排序规则和学生数据结构的信息,可以编写一个 cmp 函数定义 sort 的比较规则。这里注意,C++ 的比较运算符会根据比较结果返回逻辑值 True 或 False.

    bool cmp( Student a , Student b )
{
if( a.score != b.score )
return a.score < b.score ; // b 的分数比 a 高时,返回值为 true ,此时将 b 排在 a 前面
elsereturn a.sno > b.sno ; // b 的学号比 a 低时,返回值为 true,此时将 b 排在 a 前面
}

  对一个包含有 100 个学生信息的数组 Student a[ 100 ] 进行排序,则只需通过 sort( a , a + 100 , cmp ) 调用即可。

  注: sort 的第一种调用形式实际是使用 < 运算符对待排序数据进行比较和排序( 小者在前 ),故而若使用者为自定义的数据结构定义了 < 运算符,则也可以直接使用 sort 的第一种形式进行排序。

  qsort

  qsort 为 C 语言标准库提供的快速排序算法接口,在使用时需要包括 C 标准库 stdio.h 或 C++ 库 cstdlib 。相比于 C++ 提供的 sort ,qsort 由于涉及更多的指针操作在使用时相对而言更加复杂。qsort 函数的函数原型如下所示。  

    void qsort (void* base, size_t num, size_t size,     //base 为比较元素的起始地址,num 为待比较元素的个数,size 为单个待比较元素占用的字节长度
int (*compar)(const void*,const void*)); //compar 为函数指针,用于规定元素比较规则

  在使用 qsort 函数时,待比较数据的起始位置 base 、待比较数据的数量 num 和单个数据所占用的字节数 size 共同指定了待比较数据所在区域。而函数指针 compar 则指定了如何对上述区域中的元素进行比较。

  这里主要介绍下比较函数 compar 的写法。如 qsort 的函数原型所示,函数 compar 使用两个 void * 指针作为参数,故而在函数内部进行元素比较时,需要对上述指针进行类型转换以符合原始比较数据的类型格式,函数的返回值为 int 类型,函数返回值小于 0 时,将第一个参数放置在第二个参数前面,返回值大于 0 时,将第一个参数放置在第二个参数后面。下面以 sort 中的排序要求实现使用 qsort 时所需的具体的排序函数。注意 C 语言的比较运算符返回值为 0 和 1 ,和上述比较函数要求返回的正值和负值略有不同,可以使用 exp1? exp2 : exp3 形式的方式简化程序。

    int compareStudent( const void *a , const void *b )
{
if( ( Student * ) a -> socre != ( Student * ) b -> score )
return ( ( Student * ) a -> socre > ( Student * ) b -> score ) ? : ;
else
return ( ( Student * ) a -> sno < ( Student * ) b -> sno ) ? : ;
}

  在定义好比较函数后,以 sort 中的情况为例,调用的方式 qsort 函数的方式如下所示。

    qsort( a , 100 , sizeof( Student ) , compareStudent );        //使用 compar 函数对一百个学生的数据进行排序

  另注:虽然 C 和 C++ 为用户提供了方便快捷的快速排序接口,但在实际的算法学习过程中,理解算法的原理和享受算法所带来的方便一样重要。故而除了学习上述接口的使用外,也应该了解和掌握基础的排序算法的原理和具体实现,让自己不局限于做一个仅会使用别人提供的工具的人,自勉。

  参考:

  sort - C++ Reference

  qsort - C++ Reference

  算法笔记 p235-242

  王道论坛计算机考研机试指南 - 2.1 排序

算法学习笔记——sort 和 qsort 提供的快速排序的更多相关文章

  1. 并发编程学习笔记(4)----jdk5中提供的原子类及Lock使用及原理

    (1)jdk中原子类的使用: jdk5中提供了很多原子类,它会使变量的操作变成原子性的. 原子性:原子性指的是一个操作是不可中断的,即使是在多个线程一起操作的情况下,一个操作一旦开始,就不会被其他线程 ...

  2. 某科学的PID算法学习笔记

    最近,在某社团的要求下,自学了PID算法.学完后,深切地感受到PID算法之强大.PID算法应用广泛,比如加热器.平衡车.无人机等等,是自动控制理论中比较容易理解但十分重要的算法. 下面是博主学习过程中 ...

  3. C / C++算法学习笔记(8)-SHELL排序

    原始地址:C / C++算法学习笔记(8)-SHELL排序 基本思想 先取一个小于n的整数d1作为第一个增量(gap),把文件的全部记录分成d1个组.所有距离为dl的倍数的记录放在同一个组中.先在各组 ...

  4. Manacher算法学习笔记 | LeetCode#5

    Manacher算法学习笔记 DECLARATION 引用来源:https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途:寻找一个字符串的 ...

  5. Johnson算法学习笔记

    \(Johnson\)算法学习笔记. 在最短路的学习中,我们曾学习了三种最短路的算法,\(Bellman-Ford\)算法及其队列优化\(SPFA\)算法,\(Dijkstra\)算法.这些算法可以快 ...

  6. Johnson 全源最短路径算法学习笔记

    Johnson 全源最短路径算法学习笔记 如果你希望得到带互动的极简文字体验,请点这里 我们来学习johnson Johnson 算法是一种在边加权有向图中找到所有顶点对之间最短路径的方法.它允许一些 ...

  7. R语言实现关联规则与推荐算法(学习笔记)

    R语言实现关联规则 笔者前言:以前在网上遇到很多很好的关联规则的案例,最近看到一个更好的,于是便学习一下,写个学习笔记. 1 1 0 0 2 1 1 0 0 3 1 1 0 1 4 0 0 0 0 5 ...

  8. 二次剩余Cipolla算法学习笔记

    对于同余式 \[x^2 \equiv n \pmod p\] 若对于给定的\(n, P\),存在\(x\)满足上面的式子,则乘\(n\)在模\(p\)意义下是二次剩余,否则为非二次剩余 我们需要计算的 ...

  9. Python—kmeans算法学习笔记

    一.   什么是聚类 聚类简单的说就是要把一个文档集合根据文档的相似性把文档分成若干类,但是究竟分成多少类,这个要取决于文档集合里文档自身的性质.下面这个图就是一个简单的例子,我们可以把不同的文档聚合 ...

随机推荐

  1. HP Client Security Manager

    HP Client Security Manager - SP77916   操作系统:windows 10 64位   HP Client Security Manager - SP77916.ex ...

  2. python 字典转成对象

    database = { "key1": { 'period':999, "data": { 'a':1, 'b':2, } }, "key2&quo ...

  3. .NetCore快速搭建ELK分布式日志中心

    懒人必备:.NetCore快速搭建ELK分布式日志中心   该篇内容由个人博客点击跳转同步更新!转载请注明出处! 前言 ELK是什么 它是一个分布式日志解决方案,是Logstash.Elastaics ...

  4. 读《PMI 分析手册》

    目录 读<PMI 分析手册> 官方 PMI 基本概况 官方制造业 PMI 官方非制造业 PMI 综合 PMI 产出指数 PMI 分析框架 PMI 与经济周期 官方 PMI 分析 参考研报 ...

  5. linux下安装谷歌拼音输入法

    linux下安装谷歌拼音输入法 输入以下命令,等待安装完成. sudo apt-get install fcitx 接着输入,完成安装谷歌中文输入法 sudo apt-get install fcit ...

  6. Symbol 小妙处

    input 框输入后发送异步请求,页面拿到响应进行渲染.但偶尔会遇到问题:响应内容和输入结果不一致.因为 http 无法保证响应到达的顺序. 如何解决呢?提供一个小思路. myRequest.js i ...

  7. ubuntn18 docker zabbix+grafana安装和使用

    在ubuntu docker inflxudb(安装 使用 备份 还原 以及python编码) telegraf Grafana我采用telegraf采集数据, 本文计划采用zabbix来才采集数据, ...

  8. 使用预编译库PREBUILT LIBRARY官方说明

    使用预编译库 NDK 支持使用预编译库(同时支持静态库和共享库).此功能有以下两个主要用例: 向第三方 NDK 开发者分发您自己的库(而不分发您的源代码). 使用您自己的库的预编译版本来提升编译速度. ...

  9. Prometheus 标签使用示例整合

    Prometheus 监控实例 一.Prometheus 根据标签聚合总CPU使用率 1.主机添加标签(可在多个主机内添加相同标签实现聚合):vim prometheus.conf static_co ...

  10. Linux 常用文件描述

    Linux 常用文件描述 /etc/issue 本地登陆显示的信息,本地登录前 /etc/issue.net 网络登陆显示的信息,登录后显示,需要由sshd配置 /etc/motd 常用于通告信息,如 ...