`
bluefivecn
  • 浏览: 11676 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

数组排序

阅读更多
http://blog.ablepear.com/2011/11/objective-c-tuesdays-sorting-arrays.html

使用qsort()为C数组排序

C标准库包含一个内置的为数组排序的方法:qsort(),这是快速排序算法的一个实现。其排序之后的结果仍然放在原数组中

qsort() 的函数声明是这样:
qsort(void *array, size_t itemCount, size_t itemSize,
     int (*comparator)(void const *, void const *));

如果你没有在C中使用过函数指针,qsort()的函数声明看上去会有点让人迷惑。这是因为声明一个C函数指针类型有点唬人。我会用typedef让它看上去容易理解一些:
// alternate declaration of qsort using a typedef:
typedef int (*Comparator)(void const *, void const *);

qsort(void *array, size_t itemCount, size_t itemSize,
     Comparator comparator);

函数指针和函数的声明在C中是大体相同的,唯一的区别是函数指针在函数名前有一个*,像其他变量类型的指针一样。但有一个问题。在一个函数指针的声明里,*会引起歧义;默认情况下,C会认为*是函数返回省的一部分.因些当你声明一个函数指针的时候,需要为*和函数名加括号.这样便于编译器识别.
// 声明一个函数,返回int类型的指针
int *returnAPointerToSomeInt(void);
// 与下面这个声明相同:
// (int *)returnAPointerToSomeInt(void);

// 声明一个函数指针,这个函数返回类型是int
int (*returnSomeInt)(void);

既然我们已经说清楚了函数指针,让我们再来看看qsort()的函数声明
typedef int (*Comparator)(void const *, void const *);

qsort(void *array, size_t itemCount, size_t itemSize,
     Comparator comparator);

qsort()的前三个参数指定了要排序的数组,数组中元素的数量和单元元素的大小(字节数)
注意数组的类型是 void *,这就允许我们可以为任意类型的数组排序.

最后一个参数是比较函数.
typedef int (*Comparator)(void const *item1, void const *item2);

比较函数使用两个指向数组中元素的指针,如果item1在item2前,返回一个负值,如果item1在item2后,返回一个正值,如果两个元素有相同的排序值,返回0.这种风格的比较函数被用在许多语言的排序中. 理解比较函数可以看下面的图:


  item1 <=====<< item2
<-+------+-----+------+------+->
-2     -1     0      1      2

          item2 >>=====> item1
<-+------+-----+------+------+->
-2     -1     0      1      2

C标准库没有太多的比较函数,但比较函数很容易编写。这里是个比较int类型数据的例子:
int compareInts(void const *item1, void const *item2) {
 int const *int1 = item1;
 int const *int2 = item2;
 return *int1 - *int2;
}

现在我们可以使用compareInts()来排序一个int型的数组了:
int array[6] = { 42, 17, 57, 19, 11, 5 };

qsort(array, 6, sizeof(int), compareInts);
// array now contains 5, 11, 17, 19, 42, 57

qsort()非常灵活.对复杂类型的数组进行排序和对int类型的数组一样简单.为一个C string数组按词典排序,可以使用标准库中的strcmp()作为比较函数.
char const *array[3] = { "red", "green", "blue" };

qsort(array, 3, sizeof(char const *), strcmp);
// array now contains "blue", "green", "red"


为一个CGPoints的数组排序,先写一个比较函数:
int compareCGPoints(void const *item1, void const *item2) {
 struct CGPoint const *point1 = item1;
 struct CGPoint const *point2 = item2;

 if (point1->x < point2->x) {
   return -1;
 } else if (point1->x > point2->x) {
   return 1;
 }

 if (point1->y < point2->y) {
   return -1;
 } else if (point1->y > point2->y) {
   return 1;
 }

 return 0;
}

注意我们先比较点的X坐标,只在X坐标相等的情况下才比较Y坐标.这是比较struct中多个字段的通用方式。这是一个CGPoint比较的例子:
struct CGPoint pointArray[4] = {
 { 4.0f, 3.0f },
 { 2.0f, 1.0f },
 { 4.0f, 1.0f },
 { 2.0f, 3.0f }
};
qsort(pointArray, 4, sizeof(struct CGPoint), compareCGPoints);
// pointArray now contains:
//  { 2.0f, 1.0f }
//  { 2.0f, 3.0f }
//  { 4.0f, 1.0f }
//  { 4.0f, 3.0f }


其他C排序函数
对于大多数的普通排序工作,qsort()是个不错的选择,并且是C标准库是的内置的唯一选择。OS X和iOS也包含其他一些值得一提的排序函数:heapsort()和mergesort(),它们和qsort使用同样的参数.heapsort() 比qsort() 慢,但是排序过程中使用有限的内存, qsort() 使用递归并且可能导致堆栈溢出. 当数组已经大分部已经有序的情况下mergesort()比qsort()快很多,但是在数组很随机的情况下会慢很多.

NSArray排序

Objective-C 提供许多 NSArray排序的方法.因为NSArray 对象是不可修改的,所以用于排序 NSArray 的方法都返回一个新的排序好的 NSArray 对象,原始的NSArray不变. 最基本的排序方法是-sortedArrayUsingFunction:context:, 它和使用qsort()排序 C 相似. 函数声明是这样:
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator 
                              context:(void *)context

第一个参数是比较函数的指针,
像我们为 qsort()做的那样, 我将要使用typedef重写函数指针方法声明,以便于阅读:
typedef NSInteger (*Comparator)(id item1, id item2, void *context);

- (NSArray *)sortedArrayUsingFunction:(Comparator)comparator 
                              context:(void *)context

NSArray排序用的比较函数和qsort的比较函数稍有不同.它的返回值是NSInteger类型的,其实NSInteger只是int的一个typedef.它使用两个id类型的元素,而不是void const *,因为 NSArrays 只能容纳 object 类型.并且最后,还有一个额外的 context 参数, 一个 void 指针,这个指针允许你传递额外的信息给比较函数.

让我们写一个按NSString长度排序的比较函数.
static NSInteger compareStringsByLength(id item1, id item2, void *context) {
  return [item1 length] - [item2 length];
}

因为我们可以传递任务消息给一个id类型的变量,所以我们甚至不需要类型转换或中间变量.

下面看看我们怎么使用它:
NSArray *array = [NSArray arrayWithObjects:@"Florida", 
                    @"Texas", @"Mississippi", @"Delaware", nil];

NSArray *sortedArray = [array sortedArrayUsingFunction:compareStringsByLength 
                                               context:NULL];
// sortedArray contains:
// @"Texas"
// @"Florida"
// @"Delaware"
// @"Mississippi"

现在让我们使用context参数来方便地在普通和逆序排序之间切换.我们能传递参数给任务类型的数据,所以我们使用一个BOOL类型的指针,YES代表逆序,NO代表普通排序.
NSInteger compareStringsByLength(id item1, id item2, void *context) {
  BOOL *reversed = context;
  NSInteger order = [item1 length] - [item2 length];
  if (*reversed) {
    return -order;
  } else {
    return order;
  }
}

现在我们需要传递值给context参数当我们调用-sortedArrayUsingFunction:context:的时候:
NSArray *array = [NSArray arrayWithObjects:@"Florida", 
                    @"Texas", @"Mississippi", @"Delaware", nil];

BOOL reversed = YES;
NSArray *sortedArray = [array sortedArrayUsingFunction:compareStringsByLength 
                                               context:&reversed];
// sortedArray contains:
// @"Mississippi"
// @"Delaware"
// @"Florida"
// @"Texas"

注意我们用&操作符来传递变量reversed的地址作为context.

如果你的目标系统是iOS3.2, OS X 10.6以上,你可以用block版,-sortedArrayUsingComparator:. 我们可以这样重写我们的例子:
NSArray *array = [NSArray arrayWithObjects:@"Florida", 
                    @"Texas", @"Mississippi", @"Delaware", nil];

BOOL reversed = YES;
NSArray *sortedArray = [array sortedArrayUsingComparator:^(id item1, id item2) {
  NSInteger order = [item1 length] - [item2 length];
  if (reversed) {
    return -order;
  } else {
    return order;
  }
}];
// sortedArray contains:
// @"Mississippi"
// @"Delaware"
// @"Florida"
// @"Texas"


因为所有在NSArray中的元素必需是对象,经常的情况是这些元素自身带有比较方法.如果是这样的话,-sortedArrayUsingSelector: 方法非常好。NSString类型的NSArray非常常见.
NSArray *tagNames = [NSArray arrayWithObjects:@"H1", 
                    @"body", @"A", @"Head", nil];

NSArray *sortedTagNames = [tagNames sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
// sortedTagNames contains:
// @"A"
// @"body"
// @"H1"
// @"Head"
分享到:
评论

相关推荐

    C#实现对二维数组排序的方法

    总结来说,本文介绍的C#实现二维数组排序的方法,通过将二维数组转换为`DataTable`并利用其内置的排序功能,提供了一种灵活且高效的解决方案。这种方法不仅适用于各种数据类型,而且保持了原始数组的引用,使得排序...

    易语言自定义数据类型数组排序

    本话题聚焦于“易语言自定义数据类型数组排序”,将深入探讨如何在易语言中创建、操作自定义数据类型数组,并实现各种排序算法,如根据产地、类别和售价等属性进行排序。 自定义数据类型在易语言中允许我们定义包含...

    LabVIEW二维数组排序.rar

    总结来说,LabVIEW中的二维数组排序涉及理解二维数组的结构,掌握各种排序方法,包括按行、按列及自定义排序,以及处理数据类型转换和性能优化。熟练掌握这些技能将使你在LabVIEW编程中游刃有余,处理各种数据处理...

    易语言数组排序源码.zip

    在"易语言数组排序源码.zip"这个压缩包中,我们可以期待找到一些关于易语言如何实现数组排序的示例代码。数组排序是计算机科学中的基础操作,它在各种算法和数据处理中都有着广泛的应用。 数组排序通常涉及两种主要...

    c语言的基本算法 数组排序

    本篇内容将深入探讨C语言中的数组排序算法。 首先,数组排序是算法设计中常见的问题,它涉及到数组元素的重新排列,以达到特定的顺序,例如升序或降序。这里提到了两种基本的排序算法:筛选法(用于求素数)和选择...

    Matlab数组排序详解docx文档下载

    在MATLAB中,数组排序是数据处理和分析过程中的常见操作。`sort`函数是MATLAB提供的一种方便的工具,可以对各种类型的数组进行升序或降序排序。以下是对`sort`函数的详细说明: 1. **基本用法**: `B = sort(A)` ...

    易语言数组排序算法集合

    本资源“易语言数组排序算法集合”提供了多种常见的排序算法的源代码实现,对于学习易语言以及算法理解都有极大的帮助。下面将详细介绍其中提及的几种排序算法。 1. **冒泡排序**: 冒泡排序是最基础的排序算法之...

    文本数组排序模块测试程序

    在IT行业中,数组排序是一个非常基础且重要的概念,特别是在编程领域。数组是数据结构的一种,它存储一组相同类型的元素,并且这些元素可以通过索引进行访问。排序则是将数组中的元素按照特定规则(如升序或降序)...

    VB多维数组排序源码

    VB多维数组排序源码

    VB二维数组排序源码

    VB二维数组排序源码

    matlab数组排序方法.docx

    在 MATLAB 中,数组排序是一个非常常见的操作,尤其在数据分析和科学计算中。MATLAB 提供了多种内置函数来满足不同的排序需求。以下是一些主要的排序方法及其详细说明: 1. **sort 函数**: - `sort(A)`:对一维...

    任意数组排序

    任意数组排序 很经典经典 学习交流

    VB070-数组排序 源代码

    在编程领域,数组排序是一个非常基础且重要的概念,尤其在Visual Basic (VB)中,它在数据处理和算法实现上扮演着关键角色。本资源"VB070-数组排序 源代码"提供了一组关于如何在VB环境中对数组进行排序的源代码示例,...

    .net属性数组排序.rar

    在.NET框架中,属性数组排序是一项常见的操作,特别是在ASP.NET开发中。这涉及到对对象集合进行排序,这些对象具有特定的属性,我们希望通过这些属性值来确定集合中的顺序。本篇将深入探讨如何使用.NET Framework...

    数组排序知识代码(c#)

    在本文中,我们将深入探讨C#编程语言中的数组排序知识,并通过实际的代码示例来阐述这一主题。C#是一种广泛应用于开发Windows桌面应用、Web应用和服务端软件的强大语言,而数组作为C#中的基本数据结构,是进行数据...

    一维数组排序标程

    一维数组排序标程,绝对AC,时间复杂度O(n logn),解压密码:JYQJYQFUCKYOU

    易语言源码易语言自定义数据类型数组排序.rar

    易语言源码易语言自定义数据类型数组排序.rar 易语言源码易语言自定义数据类型数组排序.rar 易语言源码易语言自定义数据类型数组排序.rar 易语言源码易语言自定义数据类型数组排序.rar 易语言源码易语言自定义...

    matlab数组排序matlab数组排序

    matlab数组排序matlab数组排序matlab数组排序matlab数组排序matlab数组排序matlab数组排序matlab数组排序matlab数组排序matlab数组排序matlab数组排序matlab数组排序matlab数组排序matlab数组排序matlab数组排序...

    排序函数(数字或字符串数组排序)

    为普通数组和对象数组排序,对象数组排序时,可指定排序所依据的对象属性,汉字将以汉语拼音为序。

    8086汇编语言数组排序

    找了好多地方没有找到,自己写一个汇编语言实现的数组排序。

Global site tag (gtag.js) - Google Analytics