@interface NSMutableArray (HeapSort)
- (void)heapSortUsingComparator:(NSComparator)comparator;
@end
#import "NSMutableArray+HeapSort.h"
@implementation NSMutableArray (HeapSort)
- (void)heapSortUsingComparator:(NSComparator)comparator
{
if (!comparator) {
return;
}
[self buildHeapUsingComparator:comparator];
NSInteger count = [self count];
for (NSInteger index = count - 1; index >= 1; index--) {
//交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面
[self exchangeObjectAtIndex:index withObjectAtIndex:0];
//重新调整堆顶节点成为大顶
[self adjustHeapUsingComparator:comparator forIndex:0 needAdjustCount:index];
}
}
#pragma mark - PrivateMethod
- (void)buildHeapUsingComparator:(NSComparator)comparator
{
NSInteger count = [self count];
//非叶节点最大序号值为count/2
for (NSInteger index = count / 2 - 1; index >= 0; index--) {
[self adjustHeapUsingComparator:comparator forIndex:index needAdjustCount:count];
}
}
- (void)adjustHeapUsingComparator:(NSComparator)comparator forIndex:(NSInteger)index needAdjustCount:(NSInteger)needAdjustCount
{
NSInteger leftChildIndex = index * 2 + 1;
NSInteger rightChildIndex = index * 2 + 2;
NSInteger maxValueIndex = index;
if ( (leftChildIndex < needAdjustCount) && comparator(self[leftChildIndex], self[maxValueIndex]) == NSOrderedDescending) {
maxValueIndex = leftChildIndex;
}
if ( (rightChildIndex < needAdjustCount) && comparator(self[rightChildIndex], self[maxValueIndex]) == NSOrderedDescending) {
maxValueIndex = rightChildIndex;
}
if (maxValueIndex != index) {
[self exchangeObjectAtIndex:index withObjectAtIndex:maxValueIndex];
//避免调整之后以max为父节点的子树不是堆
[self adjustHeapUsingComparator:comparator forIndex:maxValueIndex needAdjustCount:needAdjustCount];
}
}
@end
测试代码
@interface Person : NSObject
@property (nonatomic, assign) NSInteger age;
@end
@implementation Person
- (NSString *)description
{
return [NSString stringWithFormat:@"Person:%p, age:%ld",self, (long)self.age];
}
@end
NSMutableArray<Person *> *arr = @[].mutableCopy;
for (NSInteger index = 0; index < 15; index++) {
Person *person = [[Person alloc] init];
person.age = arc4random() % 128;
[arr addObject:person];
}
NSLog(@"%@", arr);
[arr heapSortUsingComparator:^NSComparisonResult(Person * _Nonnull obj1, Person * _Nonnull obj2) {
if (obj1.age > obj2.age) {
return NSOrderedDescending;
} else if (obj1.age < obj2.age ) {
return NSOrderedAscending;
else {
return NSOrderedSame;
}
}];
NSLog(@"sort %@", arr);