谈如何使用c中的qsort快速排序库函数 按主次关键字正确排序
快排的效率很快,但是我们很少知道如何利用它进行多关键字排序,比如我想对一个数组a[i][0]进行的一个元素进行主关键字排序,又想对a[i][1]进行次关键字排序。那么接下来就是解决这个问题的方法。
学过数据结构的同学,应该知道快排的基本原理,就是将要排序的物品(不说成值,因为我们可能要排多维数组或者是结构体),就是每次将一个物品放到序列中最合适的位置,那么如何放,如果想要递增排序,就是前面的物品和后面的物品,谁大的放后面。所以通过这个原理就知道void qsort(void*, size_t, size_t, int*(const void*, const void*));这个函数传参数的时候为什么最后一个参数是一个函数了,真正进行排序交换的是qsort(),但是还需要一个比较两个物品的大小的操作,这个操作是需要用户自定义的,如果需要物品递增,那么这个比较函数cmp()返回的就是a>b[a-b]的true结果,这个时候排序的时候会把大的交换到后面。同理,要想物品递减,那么cmp()返回的就是a<b[b-a]了。
现在关键的问题来了。
如果排序仅仅是一个int a[N]的数组
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
//我来解释一下为什么会 return *(int *)a-*(int *)b;这个,因为我们传进到cmp()的参数是单个物体的地址,在这里我们传的是一个存储int值的一个int类型的地址,为了保持cmp()函数的可以让任何类型的数组进行比较大小,所以再传入到cmp()里面就会被转为不可变的const 的空void类型的地址,所以当我们在这个函数内部要比较大小时,又必须将这个地址转换成存储Int类型的地址,然后去取这个地址的值进行大小比较。所以(int *)a是将这个存储空类型void的地址强转换为存储int类型的地址,而只得到这个地址是比较不了大小的,这个时候就必须比较这个存储这个地址的内容了,获得地址内容只要在地址之前加上*号就可以了即*(int*)a这个的实际意义。
同理如果你要比较结构体数组,就需要在cmp内部把const void *a单个结构体成员的地址然后就是去结构体中需要比较大小的关键字了
int cmp( const void *a ,const void *b)
{
return (*(Node *)a).data > (*(Node *)b).data ? 1 : -1; //或者true,false
} qsort(s,100,sizeof(s[0]),cmp);
根据这个结构体我们,同理可推出比较多维数组,这里我们用二维数组的例子,用二维数组的第二个值作为排序的关键字
int a[1000][2];qsort(a,1000,sizeof(int)*2,comp);
intcomp(constvoid*a,constvoid*b){return((int*)a)[1]-((int*)b)[1];}{
if( ((int *)a)[0]==((int *)b)[0] ) return ((int *)a)[1]-((int *)b)[1];
else return ((int *)a)[0]-((int *)b)[0];
}
谈如何使用c中的qsort快速排序库函数 按主次关键字正确排序的更多相关文章
- C++ sort函数用法 C中的qsort
需要包含#include <algorithm>MSDN中的定义: template<class RanIt> void sort(RanIt first, RanIt ...
- C中的qsort函数和C++中的sort函数的理解与使用
一.qsort()函数 原型:_CRTIMP void __cdecl qsort (void*, size_t, size_t,int (*)(const void*, const void*)); ...
- 浅谈线程池(中):独立线程池的作用及IO线程池
原文地址:http://blog.zhaojie.me/2009/07/thread-pool-2-dedicate-pool-and-io-pool.html 在上一篇文章中,我们简单讨论了线程池的 ...
- 【ASP.NET MVC系列】浅谈NuGet在VS中的运用
一 概述 在我们讲解NuGet前,我们先来看看一个例子. 1.例子: 假设现在开发一套系统,其中前端框架我们选择Bootstrap,由于选择Bootstrap作为前端框架,因此,在项目中,我们 ...
- 浅谈surging服务引擎中的rabbitmq组件和容器化部署
1.前言 上个星期完成了surging 的0.9.0.1 更新工作,此版本通过nuget下载引擎组件,下载后,无需通过代码build集成,引擎会通过Sidecar模式自动扫描装配异构组件来构建服务引擎 ...
- 浅谈如何检查Linux中开放端口列表
给大家分享一篇关于如何检查Linux中的开放端口列表的详细介绍,首先如果你想检查远程Linux系统上的端口是否打开请点击链接浏览.如果你想检查多个远程Linux系统上的端口是否打开请点击链接浏览.如果 ...
- iOS中assign、copy 、retain等关键字的含义
iOS中assign.copy .retain等关键字的含义 转自:http://my.oschina.net/majiage/blog/267409 assign: 简单赋值,不更改索引计数cop ...
- SQLSERVER中的ALL、PERCENT、CUBE关键字、ROLLUP关键字和GROUPING函数
SQLSERVER中的ALL.PERCENT.CUBE关键字.ROLLUP关键字和GROUPING函数 先来创建一个测试表 USE [tempdb] GO )) GO INSERT INTO [#te ...
- 在windows中,如何使用cmd命令行窗口正确显示编码为utf-8格式的文字
在windows中,如何使用cmd命令行窗口正确显示编码为utf-8格式的文字呢? 正确的步骤如下: 1, 打开cmd命令行窗口 2, 输入命令 >chcp 65001 数字65001代表的是c ...
随机推荐
- Oracle EBS-SQL (GL-4):从接收追溯到接收事务
SELECT row_id, creation_date, created_by, last_update_date, last_updated_by,last_update_login, note_ ...
- oracle sql命令行中上下左右使用
yum -y install readline,rlwrap
- 【转】Python3.x移除了callable内建函数
原文地址:http://www.cnblogs.com/elvisxu/archive/2010/10/26/1861958.html 最近学习Python的时候,在Python3下跑<Dive ...
- append与after区别
append() & prepend()实在元素内插入内容(该内容变成该元素的子元素或节点),after() & before()是在元素的外面插入内容(其内容变成元素的兄弟节点).
- mac pro 设置wifi热点
系统偏好设置-共享-网络共享(Internet共享)共享来源选择你的网络(非wifi), 以下复选框选wifi,wifi设置里能够设置wifi名字password,注意不能有中文. 设置完,inter ...
- 遍历GridView
].Text+"--------------"); } }
- matlab改变GUI和figure左上角图标的方法,并生成exe文件
1. GUI左上角图标的更改,假设GUI的Tag为figure1,在其OpeningFcn里添加h = handles.figure1; %返回其句柄newIcon = javax.swing.Ima ...
- 数据持久化------Archiving(归档,解档)
其中TRPerson为自定义的继承自NSObject的类的子类 其中有两个属性,name 和 age .h文件 #import @interface TRPerson : NSObject<& ...
- .wsdl文件生成.cs文件
1.打开VS文件命令行工具(一般在安装文件的Common7\Tools\Shortcuts下面例如[E:\VS2013安装程序\Common7\Tools\Shortcuts\VS2013 x64 本 ...
- spring schema自定义
今天看了一下分布式服务框架的那本书,于是里面提到了spring schema的自定义,于是去简单的了解了一下 参考资源:spring schema扩展: http://www.yihaomen.com ...