EKAlgorithms-常用数据结构Objective-C语言实现一数组排序

EKAlgorithms

EKAlgorithms is a set of computer exercises implemented in Objective-C. Data structures, well known algorithms, CS curiosities, you name it!
EKAgorithms 是一系列通过Objective-C语言实现的计算机代码。包含一些数据结构,众所周知的算法如排序,查找,字符串,二叉树,图
此文章只对该框架进行介绍,暂不讲解算法实现原理。

NSArray+EKStuff

1.获取数组中最大元素的索引

//返回数组最大值的下标
- (NSUInteger)indexOfMaximumElement
{
    id maximumValue = [self firstObject];
<span style="color:#1d9421;">
    //初始最大值下标为0
</span>    NSUInteger indexOfMaximumValue = 0;

    NSUInteger count = [self count];

    for (NSUInteger i = 1; i < count; i++) {
        id value = self[i];
        
        if ([value compare:maximumValue] == NSOrderedDescending) {
            maximumValue        = value;
            indexOfMaximumValue = i;
        }
    }
    return indexOfMaximumValue;
}
2.获取存储字符串数组的最长字符串

- (NSString *)longestString
{
    NSString *returnValue = nil;
    for (NSString *string in self) {
        if (returnValue == nil || ([string length] > [returnValue length])) {
            returnValue = string;
        }
    }
    return returnValue;
}
3.求两个数组的交集

<span style="font-size:14px;"><strong>- (NSArray *)intersectionWithArray:(NSArray *)secondArray
{
    NSMutableSet *intersection = [NSMutableSet setWithArray:self];
    [intersection intersectSet:[NSSet setWithArray:secondArray]];

    return [intersection allObjects];
}</strong></span>
4.求两个数组的并集
- (NSArray *)unionWithoutDuplicatesWithArray:(NSArray *)secondArray
{
    NSSet *firstSet  = [NSSet setWithArray:self];
    NSSet *secondSet = [NSSet setWithArray:secondArray];
    
    NSMutableSet *resultSet = [NSMutableSet setWithSet:firstSet];
    [resultSet unionSet:secondSet];
    return [resultSet allObjects];
}
5. 获取数组中为字典的并集(指定的Key删除重复对象)

//获取数组中为字典的并集(指定的Key删除重复对象)</span>
- (NSArray *)unionWithoutDuplicatesWithArray:(NSArray *)secondArray forKey:(NSString *)currentKey
{
    NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:self];
    [mutableArray addObjectsFromArray:secondArray];

    NSArray *copy = [mutableArray copy];
    NSUInteger index = [copy count] - 1;
    <span style="color:#009900;">//reverseObjectEnumerator倒序遍历</span>
    for (id object in [copy reverseObjectEnumerator]) {
        
        for (NSUInteger i = 0; i < index; i++) {
            if ([[mutableArray[i] valueForKey:currentKey] isEqualToString:[object valueForKey:currentKey]]){
                [mutableArray removeObjectAtIndex:index];
                break;
            }
        }
        index --;
    }
    return mutableArray;
}
6. 检测数组中是否包含相同元素

- (BOOL)hasDuplicates
{
    NSMutableDictionary *registry = [[NSMutableDictionary alloc] initWithCapacity:self.count];

    for (id element in self) {
        NSNumber *elementHash = @([element hash]);
        
        if (registry[elementHash] == nil) {
            registry[elementHash] = element;
        }
        else {
            NSLog(@"-[NSArray hasDuplicates] found duplicate elements: %@ and %@", registry[elementHash], element);
            return YES;
        }
    }
    return NO;
}

NSArray+EKSorting

7.判断数组元素是否有序排列

- (BOOL)isSorted
{
    NSUInteger countMinusOne = self.count - 1;

    for (NSUInteger i = 0; i < countMinusOne; i++) {
        if ([self[i] compare:self[i + 1]] == NSOrderedDescending) {
            return NO;
        }
    }

    return YES;
}
8.数组逆置

- (NSMutableArray *)reverse
{
    NSUInteger count = self.count;

    for (int i = 0; i < count / 2; i++) {
        [self exchangeObjectAtIndex:i withObjectAtIndex:(count - 1 - i)];
    }

    return self;
}
9.冒泡排序

思想:设数组长度为N。

1.比较相邻的前后二个数据,如果前面数据大于后面的数据,就将二个数据交换。

2.这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1个位置。

3.N=N-1,如果N不为0就重复前面二步,否则排序完成。

- (NSMutableArray *)naiveBubbleSort
{
    NSUInteger count = [self count];

    for (int i = 0; i < count; i++) {
        for (int j = 0; j < (count - 1); j++) {
            if ([self[j] compare:self[j + 1]] == NSOrderedDescending) {
                [self exchangeObjectAtIndex:j withObjectAtIndex:(j + 1)];
            }
        }
    }

    return self;
}
10.插入排序

思想:每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。

<span style="font-size:12px;">- (NSMutableArray *)insertionSort
{
    NSUInteger count = self.count;

    for (int i = 1; i < count; i++) {
        for (int j = i; (j > 0) && ([self[j - 1] floatValue] > [self[j] floatValue]); j--) {
            [self exchangeObjectAtIndex:j withObjectAtIndex:(j - 1)];
        }
    }

    return self;
}</span>
11.希尔排序

思想:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。

- (NSMutableArray *)shellSort
{
    NSUInteger count = [self count];

    for (NSInteger i = count / 2; i > 0; i = i / 2) {
        for (NSInteger j = i; j < count; j++) {
            for (NSInteger k = j - i; k >= 0; k = k - i) {
                if ([self[k + 1] floatValue] >= [self[k] floatValue]) {
                    break;
                }
                else {
                    [self exchangeObjectAtIndex:k withObjectAtIndex:(k + i)];
                }
            }
        }
    }

    return self;
}
12.归并排序

思想:利用递归和分而治之的技术将数据序列划分成为越来越小的半子表,再对半子表排序,最后再用递归步骤将排好序的半子表合并成为越来越大的有序序列

- (NSMutableArray *)mergeSort
{
    NSUInteger count = [self count];
    
    [self partitionArrayWithMinimalIndex:0 withMaximumIndex:(count - 1)];
    
    return self;
}
- (void)partitionArrayWithMinimalIndex:(NSInteger)min withMaximumIndex:(NSInteger)max
{
    NSInteger mid = 0;
    
    if (min < max) {
        mid = (min + max) / 2;
        [self partitionArrayWithMinimalIndex:min withMaximumIndex:mid];
        [self partitionArrayWithMinimalIndex:mid + 1 withMaximumIndex:max];
        [self mergeArrayWithMinimalIndex:min withMediumIndex:mid withMaximalIndex:max];
    }
}

- (void)mergeArrayWithMinimalIndex:(NSInteger)min withMediumIndex:(NSInteger)mid withMaximalIndex:(NSInteger)max
{
    NSMutableArray *temporaryArray = [NSMutableArray array];

    NSUInteger count = [self count];

    for (NSInteger i = 0; i < count; i++) {
        [temporaryArray addObject:[NSNull null]];
    }

    NSInteger i = 0, j = 0, k = 0, m = 0;
    j = min;
    m = mid + 1;

    for (i = min; j <= mid && m <= max; i++) {
        if ([self[j] floatValue] <= [self[m] floatValue]) {
            temporaryArray[i] = self[j];
            j++;
        }
        else {
            temporaryArray[i] = self[m];
            m++;
        }
    }
    if (j > mid) {
        for (k = m; k <= max; k++) {
            temporaryArray[i] = self[k];
            i++;
        }
    }
    else {
        for (k = j; k <= mid; k++) {
            temporaryArray[i] = self[k];
            i++;
        }
    }
    for (k = min; k <= max; k++) {
        self[k] = temporaryArray[k];
    }
}
13.选择排序

思想:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

- (NSMutableArray *)insertionSort
{
    NSUInteger count = self.count;

    for (int i = 1; i < count; i++) {
        for (int j = i; (j > 0) && ([self[j - 1] floatValue] > [self[j] floatValue]); j--) {
            [self exchangeObjectAtIndex:j withObjectAtIndex:(j - 1)];
        }
    }

    return self;
}
14.快速排序

思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

- (NSMutableArray *)quickSortWithLeftIndex:(NSInteger)left withRightIndex:(NSInteger)right
{
    NSInteger i = left;
    NSInteger j = right;
    
    id pivotalElement = nil;
    
    pivotalElement = self[(left + right) / 2];
    
    do {
        while (([self[i] floatValue] < [pivotalElement floatValue]) && (i < right)) {
            i++;
        }
        while (([pivotalElement floatValue] < [self[j] floatValue]) && (j > left)) {
            j--;
        }
        
        if (i <= j) {
            [self exchangeObjectAtIndex:i withObjectAtIndex:j];
            
            i++;
            j--;
        }
    }
    while (i <= j);
    
    if (left < j) {
        [self quickSortWithLeftIndex:left withRightIndex:j];
    }
    
    if (i < right) {
        [self quickSortWithLeftIndex:i withRightIndex:right];
    }
    
    return self;
}
15.基数排序

思想:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。

- (NSMutableArray *)radixSortForBase:(NSInteger)base
{
    int max = [[self valueForKeyPath:@"@max.intValue"] intValue];

    int numberOfSteps = (log(max) / log(base)) + 1;

    for (int i = 0; i < numberOfSteps; i++) {
        NSMutableArray *radixTable = [NSMutableArray makeRadixTableForArray:self forBase:base forDigit:i];

        [self setArray:[NSMutableArray makeArrayFromRadixTable:radixTable]];
    }

    return self;
}

+ (NSMutableArray *)makeArrayFromRadixTable:(NSMutableArray *)radixTable
{
    NSMutableArray *theArray = [NSMutableArray new];
    
    for (SSRadixNode *bucketNode in radixTable) {
        SSRadixNode *bucket = bucketNode.next;
        while (bucket) {
            [theArray addObject:@(bucket.data)];
            bucket = bucket.next;
        }
    }
    return theArray;
}

+ (NSMutableArray *)makeRadixTableForArray:(NSMutableArray *)theArray forBase:(NSInteger)base forDigit:(NSInteger)digit
{
    NSMutableArray *radixTable = [self getTableOfEmptyBucketsForSize:base];
    
    for (int i = 0; i < theArray.count; i++) {
        NSInteger value = [theArray[i] integerValue];
        NSInteger radixIndex = [self getExaminedNumber:value withBase:base atDigit:digit];
        SSRadixNode *current = (SSRadixNode *)radixTable[radixIndex];
        if (current.next) {
            while (current.next) {
                current = [current next];
            }
        }
        SSRadixNode *newEntry = [SSRadixNode new];
        newEntry.data = [theArray[i] intValue];
        current.next = newEntry;
    }
    
    return radixTable;
}

+ (NSMutableArray *)getTableOfEmptyBucketsForSize:(NSInteger)size
{
    NSMutableArray *empty = [NSMutableArray new];
    
    for (NSInteger i = 0; i < size; i++) {
        [empty addObject:[SSRadixNode new]];
    }
    
    return empty;
}

+ (NSInteger)getExaminedNumber:(NSInteger)number withBase:(NSInteger)base atDigit:(NSInteger)digit
{
    NSInteger divisor = (digit == 0) ? 1 : (pow(base, digit));
    return (number / divisor) % base;
}
16.堆排序

思想:利用堆的性质进行的一种选择排序

- (NSMutableArray *)heapSort
{
    NSUInteger count = self.count;

    [self heapifyArrayWithSize:count];

    NSInteger end = count - 1;

    while (end > 0) {
        [self exchangeObjectAtIndex:end withObjectAtIndex:0];
        [self siftDownArrayWithStart:0 end:end - 1];
        end--;
    }
    
    return self;
}
- (void)siftDownArrayWithStart:(NSInteger)startIndex end:(NSInteger)endIndex
{
    NSInteger root = startIndex;

    while ((root * 2 + 1) <= endIndex) {
        NSInteger child = root * 2 + 1;

        if (child + 1 <= endIndex && [self[child] floatValue] < [self[child + 1] floatValue]) {
            child++;
        }

        if ([self[root] floatValue] < [self[child] floatValue]) {
            [self exchangeObjectAtIndex:root withObjectAtIndex:child];
            root = child;
        }
        else {
            return;
        }
    }
}

- (void)heapifyArrayWithSize:(NSInteger)size
{
    NSInteger start = (size - 2) / 2;
    
    while (start >= 0) {
        [self siftDownArrayWithStart:start end:size - 1];
        start--;
    }
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值