算法学习笔记——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算法学习笔记
一. 什么是聚类 聚类简单的说就是要把一个文档集合根据文档的相似性把文档分成若干类,但是究竟分成多少类,这个要取决于文档集合里文档自身的性质.下面这个图就是一个简单的例子,我们可以把不同的文档聚合 ...
随机推荐
- spring扩展点之五:ApplicationContextInitializer实现与使用
ApplicationContextInitializer是Spring框架原有的东西,这个类的主要作用就是在ConfigurableApplicationContext类型(或者子类型)的Appli ...
- ubuntn18 docker zabbix+grafana安装和使用
在ubuntu docker inflxudb(安装 使用 备份 还原 以及python编码) telegraf Grafana我采用telegraf采集数据, 本文计划采用zabbix来才采集数据, ...
- Python批量更改文件名
一.问题在处理文件或者一些其他信息的时候我们需要更改文件名,那么我们可以写一个程序来修改这些文件名,以减少我们重复的做一件事. 二.解决本次使用的Python,利用的是Python中的OS模块,具体操 ...
- NOI2019游记
本来打算写退役记的,结果退役失败了,所以 非常抱歉,这篇文章鸽了.
- Java并发编程: CountDownLatch、CyclicBarrier和 Semaphore
java 1.5提供了一些非常有用的辅助类来帮助并发编程,比如CountDownLatch,CyclicBarrier和Semaphore. 1.CountDownLatch –主线程阻塞等待,最后完 ...
- 使用Dbvisualizer 连接 Elasticsearch
Dbvisualizer 安装 从网上下载该软件,并破解激活 下载地址:http://www.ddooo.com/softdown/142713.htm 1.下载解压,得到dbvisualizer p ...
- 【vue】搭建vue环境以及要安装的所有东西
参考地址: https://www.cnblogs.com/laizhouzhou/p/8027908.html
- 开源规则引擎 Drools 学习笔记 之 -- 1 cannot be cast to org.drools.compiler.kie.builder.impl.InternalKieModule
直接进入正题 我们在使用开源规则引擎 Drools 的时候, 启动的时候可能会抛出如下异常: Caused by: java.lang.ClassCastException: cn.com.cheng ...
- C#桌面程序启动时传入参数
using System;using System.Collections.Generic;using System.Linq;using System.Windows.Forms; namespac ...
- C#中如何禁止WindowsMediaPlayer双击全屏显示
问题描述:在项目中使用WindowsMediaPlayer播放视频时,双击会出现视频全屏的效果,而且视频恢复后会暂停,除非再次双击返回后才能正常播放.那么如何禁止WindowsMediaPlayer的 ...