iOS - 归并排序

Demo_github

图片源于网络

归并排序:

归并排序(Merge Sort)是建立在归并操作上的一种有效的排序算法,算法主要采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序比较占用内存,但却是一种效率高且稳定的算法。

算法思想

  • 把序列分成元素尽可能相等的两半。

  • 把两半元素分别进行排序。

  • 把两个有序表合并成一个。

综上可知,归并排序其实要做两件事:

(1)“分解”——将序列每次折半划分。
(2)“合并”——将划分后的序列段两两合并后排序。合并相邻有序子序列

图-归并排序示例图

合并相邻有序子序列过程:


合并相邻有序子序列1
合并相邻有序子序列2

范例代码

/**
 归并排序
 
 @param array 需要排序的Array
 */
+ (void)megerSort:(NSMutableArray *)array
{
    /**
     归并排序其实要做两件事:
     
     (1)“分解”——将序列每次折半划分。
     
     (2)“合并”——将划分后的序列段两两合并后排序。
     */
    //排序数组
    NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:1];
    //第一趟排序是的子数组个数为ascendingArr.count
    for (NSNumber *num in array) {
        NSMutableArray *subArray = [NSMutableArray array];
        [subArray addObject:num];
        [tempArray addObject:subArray];
    }
    /**
     分解操作 每一次归并操作 tempArray的个数为(当数组个数为偶数时tempArray.count/2;当数组个数为奇数时tempArray.count/2+1);当tempArray.count == 1时,归并排序完成
     */
    while (tempArray.count != 1) {
        NSInteger i = 0;
        
        //当数组个数为偶数时 进行合并操作, 当数组个数为奇数时,最后一位轮空
        while (i < tempArray.count - 1) {
            
            //将i 与i+1 进行合并操作 将合并结果放入i位置上 将i+1位置上的元素删除
            tempArray[i] = [self mergeArrayFirstList:tempArray[i] secondList:tempArray[i + 1]];
            [tempArray removeObjectAtIndex:i + 1];
            
            //i++ 继续下一循环的合并操作
            i++;
        }
    }
    NSLog(@"归并排序结果:%@", tempArray);
}
//合并
+ (NSArray *)mergeArrayFirstList:(NSArray *)array1 secondList:(NSArray *)array2 {
    
    // 合并序列数组
    NSMutableArray *resultArray = [NSMutableArray array];
    
    // firstIndex是第一段序列的下标 secondIndex是第二段序列的下标
    NSInteger firstIndex = 0, secondIndex = 0;
    
    // 扫描第一段和第二段序列,直到有一个扫描结束
    while (firstIndex < array1.count && secondIndex < array2.count) {
        // 判断第一段和第二段取出的数哪个更小,将其存入合并序列,并继续向下扫描
        if ([array1[firstIndex] floatValue] < [array2[secondIndex] floatValue]) {
            [resultArray addObject:array1[firstIndex]];
            firstIndex++;
        } else {
            [resultArray addObject:array2[secondIndex]];
            secondIndex++;
        }
    }
    // 若第一段序列还没扫描完,将其全部复制到合并序列
    while (firstIndex < array1.count) {
        [resultArray addObject:array1[firstIndex]];
        firstIndex++;
    }
    // 若第二段序列还没扫描完,将其全部复制到合并序列
    while (secondIndex < array2.count) {
        [resultArray addObject:array2[secondIndex]];
        secondIndex++;
    }
    // 返回合并序列数组
    return resultArray.copy;
}

算法分析

归并排序算法的性能
归并排序算法的性能
时间复杂度

归并排序的形式就是一棵二叉树,它需要遍历的次数就是二叉树的深度,而根据完全二叉树的可以得出它的时间复杂度是O(N*log N)。

空间复杂度

算法处理过程中,需要一个大小为n的临时存储空间用以保存合并序列。

算法稳定性

在归并排序中,相等的元素的顺序不会改变,所以它是稳定的算法。

归并排序和堆排序、快速排序的比较
  • 若从空间复杂度来考虑:首选堆排序,其次是快速排序,最后是归并排序。

  • 若从稳定性来考虑,应选取归并排序,因为堆排序和快速排序都是不稳定的。

  • 若从平均情况下的排序速度考虑,应该选择快速排序。

参考

排序七 归并排序

图解排序算法(四)之归并排序

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到已排序好...
    依依玖玥阅读 1,293评论 0 2
  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,248评论 0 52
  • 概述:排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    每天刷两次牙阅读 3,755评论 0 15
  • 概述排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的...
    Luc_阅读 2,327评论 0 35
  • 不凡,今天是你离开我的第105天,我用了83天的时间来接受你离开我的事实,时间用它运动过的轨迹告诉我,被生死捉弄的...
    所乙阅读 449评论 0 0