算法学习笔记——sort 和 qsort 提供的快速排序
这里存放的是笔者在学习算法和数据结构时相关的学习笔记,记录了笔者通过网络和书籍资料中学习到的知识点和技巧,在供自己学习和反思的同时为有需要的人提供一定的思路和帮助。
从排序开始
基本的排序算法包括冒泡排序、插入排序、选择排序和快速排序的算法原理从基础的数据结构教程中即可学习,不在本文的讨论范围之内。这里主要介绍的是在算法设计程序中可以直接利用的排序工具。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++ 为用户提供了方便快捷的快速排序接口,但在实际的算法学习过程中,理解算法的原理和享受算法所带来的方便一样重要。故而除了学习上述接口的使用外,也应该了解和掌握基础的排序算法的原理和具体实现,让自己不局限于做一个仅会使用别人提供的工具的人,自勉。
参考:
算法笔记 p235-242
王道论坛计算机考研机试指南 - 2.1 排序
算法学习笔记——sort 和 qsort 提供的快速排序的更多相关文章
- 并发编程学习笔记(4)----jdk5中提供的原子类及Lock使用及原理
(1)jdk中原子类的使用: jdk5中提供了很多原子类,它会使变量的操作变成原子性的. 原子性:原子性指的是一个操作是不可中断的,即使是在多个线程一起操作的情况下,一个操作一旦开始,就不会被其他线程 ...
- 某科学的PID算法学习笔记
最近,在某社团的要求下,自学了PID算法.学完后,深切地感受到PID算法之强大.PID算法应用广泛,比如加热器.平衡车.无人机等等,是自动控制理论中比较容易理解但十分重要的算法. 下面是博主学习过程中 ...
- C / C++算法学习笔记(8)-SHELL排序
原始地址:C / C++算法学习笔记(8)-SHELL排序 基本思想 先取一个小于n的整数d1作为第一个增量(gap),把文件的全部记录分成d1个组.所有距离为dl的倍数的记录放在同一个组中.先在各组 ...
- Manacher算法学习笔记 | LeetCode#5
Manacher算法学习笔记 DECLARATION 引用来源:https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途:寻找一个字符串的 ...
- Johnson算法学习笔记
\(Johnson\)算法学习笔记. 在最短路的学习中,我们曾学习了三种最短路的算法,\(Bellman-Ford\)算法及其队列优化\(SPFA\)算法,\(Dijkstra\)算法.这些算法可以快 ...
- Johnson 全源最短路径算法学习笔记
Johnson 全源最短路径算法学习笔记 如果你希望得到带互动的极简文字体验,请点这里 我们来学习johnson Johnson 算法是一种在边加权有向图中找到所有顶点对之间最短路径的方法.它允许一些 ...
- R语言实现关联规则与推荐算法(学习笔记)
R语言实现关联规则 笔者前言:以前在网上遇到很多很好的关联规则的案例,最近看到一个更好的,于是便学习一下,写个学习笔记. 1 1 0 0 2 1 1 0 0 3 1 1 0 1 4 0 0 0 0 5 ...
- 二次剩余Cipolla算法学习笔记
对于同余式 \[x^2 \equiv n \pmod p\] 若对于给定的\(n, P\),存在\(x\)满足上面的式子,则乘\(n\)在模\(p\)意义下是二次剩余,否则为非二次剩余 我们需要计算的 ...
- Python—kmeans算法学习笔记
一. 什么是聚类 聚类简单的说就是要把一个文档集合根据文档的相似性把文档分成若干类,但是究竟分成多少类,这个要取决于文档集合里文档自身的性质.下面这个图就是一个简单的例子,我们可以把不同的文档聚合 ...
随机推荐
- 【RS】Wide & Deep Learning for Recommender Systems - 广泛和深度学习的推荐系统
[论文标题]Wide & Deep Learning for Recommender Systems (DLRS'16) [论文作者] Heng-Tze Cheng, Levent Koc, ...
- docker 学习操作记录 1
记录1 Xshell (Build ) Copyright (c) NetSarang Computer, Inc. All rights reserved. Type `help' to learn ...
- UI自动化实例:遍历点击带有滚动条的列表每一项
需求:验证列表每条资讯里的用户数是否正确.该列表分页请求数据,每页10条,每次滚动到底部自动增量请求10条. 实现自动化必要性: 1 资讯每天不定时更新需经常性验证, 程序更新或者环境切换需验证所有资 ...
- 11. Scala数据结构(下)-集合操作
11.1 集合元素的映射-map映射操作 11.1.1 看一个实际需求 要求:请将List(3,5,8)中所有的元素都*2,将其结果放到一个新的集合中返回,即返回一个新的List(6,10,16),请 ...
- CRLF will be replaced by LF in XXX when git commit
转载自Git-warning: CRLF will be replaced by LF in XXX 今天,普通平凡的一天,平凡的使用 git add .,然后又出现一个之前没遇到的错误提示 . 真开 ...
- wps金山文档在线编辑--.Net 接入指南
一.申请成为服务商,对金山文档在线服务进行申请 ①进入官网 https://open.wps.cn/ ②申请后如下图,点击右下角的进入服务 ③申请成功后 ④数据回调URL一定是服务器地址,本次我使用的 ...
- Django---简易图书管理系统(B/S架构)
Django---简易图书管理系统 一丶配置 创建app01 # 1.在具有manage.py文件的目录下,启动cmd,创建一个新的app01 python manage.py startapp ap ...
- GitHub Python项目推荐|瓦力Devops开源项目代码部署平台持续部署
GitHub Python项目推荐|walle - 瓦力 Devops开源项目代码部署平台 项目热度 标星(star):8418 (很不错的实用项目,大神作品,建议关注) 标星趋势 关注(watch) ...
- BootStrap简单table
效果图: 代码如下: <%-- Created by IntelliJ IDEA. User: 冷噫雪 Date: 2019/9/1 Time: 13:06 To change this tem ...
- 几种线程相关的map介绍
Java中平时用的最多的Map集合就是HashMap了,它是线程不安全的. 看下面两个场景: 1.当用在方法内的局部变量时,局部变量属于当前线程级别的变量,其他线程访问不了,所以这时也不存在线程安全不 ...