谈如何使用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 ...
随机推荐
- 主计划MPS禁止改写项目编号(PROJECT)
应用 Oracle Manufacturing Planning 层 Level Function 函数名 Funcgtion Name MRPFSDMS-253 表单名 Form Name MR ...
- iOS6和iOS7代码的适配(3)——坐标适配
由于iOS7里面status bar和视图是重叠在一起了,所以应用的y坐标就没法和以前一致了,需要重新计算设定.基本上,你的应用用Xcode5运行一下就能看见这个问题,这里写了一个最简单的例子,一个V ...
- Oracle_系统和对象权限管理
授予系统权限: GRANT { system_privilege | role } [,{ system_privilege | role }]... ... TO {user | role | PU ...
- cdoj 斐波那契进制
//昨天在姜神的提醒下发现这种方法可以解决升级版的 非升级版直接01背包就好 //这题脑洞开得真是够大 解:大概要先把数分解成斐波拉契进制,x=f1*(0或1)+f2*(0或1)+...+fn*(0或 ...
- NSFileHandle编写json数据格式
代码如下: + (void)writeToFile:(NSDictionary *)params filePath:(NSString *)path { NSData *jsonData = [sel ...
- iOS 更改导航栏返回button文字
假如有两个ViewController A,B 改动B的返回button需在A页面设置 self.navigationItem.backBarButtonItem = [[UIBarButtonIte ...
- cocos2d-x -- 渠道SDK【棱镜】接入(2)
上一章<cocos2d-x -- 渠道SDK[棱镜]接入(1)>,已经接入好了SDK.如今要准备加入渠道了,以豌豆荚为例. 详细流程: 1.加入渠道:
- asp.net Listbox控件用法
2008-02-18 19:56 来源: 作者: ListBox(列表框)控件可以显示一组项目的列表,用户可以根据需要从中选择一个或多个选项.列表框可以为用户提供所有选项的列表.虽然也可设置列表框为多 ...
- java中关于SSL/TSL的介绍和如何实现SSL Socket双向认证
一. SSL概述 SSL协议采用数字证书及数字签名进行双端实体认证,用非对称加密算法进行密钥协商,用对称加密算法将数据加密后进行传输以保证数据的保密性,并且通过计算数字摘要来验证数据在传 ...
- js中字符串方法
字符串方法: 1. charAt(索引值)//通过索引值获取字符串中对应的值 例如: var str='sdf123'; alert(str.charAt(0));//结果弹出第一个索引对应的值:s