iOS学习笔记--归并排序

作者: 半月迎风 | 来源:发表于2017-07-26 10:20 被阅读204次

    归并排序

          百度上的解释:归并排序:是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并

    学习归并排序之前,需要理解一下分治思想。

    分治思想:

    a.将大问题划分为N个小问题,

    b.解决每个小问题,

    c.将解决完的小问题合并起来,形成一个整体,就把原来的大问题解决好了。

    应用:

            (1)二分法(二分查找),可以提高效率

                (2)小例子:找假硬币  (在8个硬币中有一个是假的,问假币是清的,还是重的)

            解决:将硬币均分为两堆(A与B)  ,对比重量,这时候A与B会不相等, 然后再分别将A与B均分 (c、 d 与 e、 f),然后一次,比较 c与d ,e与f ,此时,哪一组的重量不相等 ,假币就在哪一组。假设A 比B重,然后  ,A 中的c与d 不相等,则假币是重了, 反之就是轻了。(用这个方法再推算下去,可以得到哪个是假币)。

    归并排序的两种方式  :(1)for循环 (本文主要是介绍以for循环的方式) (2)递归

          for循环方式:讲数组分为 2个数组 -->4个--> 8个-->...知道长度为1的数组结束

    然后开始两两归并,直到得到有序数组

      相比于递归的方式的好处是减少栈空间的大小。

    例子: A[] = [ 5,3,6,2,7]

    分析:将这个数组拆分 [{5},{3},{6},{2},{7}]

    归并  两两相邻归并-->[{5},{3}, | {6},{2},{7}] ==>

    [3, 5] , [2,6] ,[7]    --> [3, 5] , [2,6] | ,[7] ==>

    [2 ,3,5,6],[7] -->[2 ,3,5,6],| [7] ==>

    [2,3,5,6,7]

    代码实现:(要注意对边界值的分析)

    将数组分开,取一个中间值 划分为两个部分

    startIndex -- middle-- endInden

    划分  :

          前一部分 :startIndex --middle

          后一部分:middle + 1 -- endIndex 

    判断当  startIndex == endIndex  -->数组问有序状态

    然后归并:(前后两部分,分别完成之后在执行)

    前一部分起始: preIndex

    后一部分起始:  nextIndex:

    preIndex的范围是在0 到middle  nextIndex的范围是在middle +1 到end

    #pragma mark -for循环方式

    +(void)sortCArray:(int*)a to:(int*)b length:(int)length groupLength:(int)groupLength{

    intstartIndex =0;

    while(startIndex < length) {

              intpreIndex = startIndex;

              intnextIndex = startIndex +groupLength;

              inti = startIndex;

              while(preIndex != startIndex + groupLength && nextIndex != startIndex +groupLength*2&& nextIndex< length) {

    //当preIndex <= nextIndex的时候

    //b[i]= a[preIndex]

                    if(a[preIndex] <= a[nextIndex]) {

                          b[i++] = a[preIndex++];

                      }else{

    //当preIndex > nextIndex的时候

    //b[i] = a[nextIndex]

                          b[i++] = a[nextIndex ++];

                      }

            }

    //判读最后升一下一个的情况 a .如果是前一部分没有完成  就归到前一部分

    while(preIndex != startIndex +groupLength && i < length) {

              b[i++]= a[preIndex++];

    }

    //b.如果是后一部分没有完成,就归到后一部分

    while(nextIndex !=startIndex + groupLength*2&& i< length) {

              b[i++]= a[nextIndex ++];

    }

              startIndex += groupLength *2;

    }

    }

    得到 b是有序的,a是无序的数组

    然后 讲b拷贝到a数组

    在举个例子解释一下实现过程  数组 a[] = [5,3,2,4,7]  (P表示preIndex N表示nextIndex )

    5, 3, 2,4, 7

    ...(省略中间部分)

    [2 ,3 ,5] | [4,7]

    b[0] -->2    2 与4 比较

    b[1]  -->3    3 与 4比较

    b[2] -->4      5与4 比较

    b[3] --> 5    5与7比较

    到这里比较完一轮 但是7还没有比较完出来

    在进行下一轮比较 由于7在后一部分 所以b[4]--7

    扩展性:

    归并类属于外排序

    稳定性:

    相等两个元素,比较,相对文字发生改变,者是不稳定,反之,是稳定的

    例子  [  2, 7 , 5, 3,5]  排序结果是[2,3,5,5,7]

    如果是 5>=5 交换位置 则是不稳定  反之则是稳定

    稳定排序  :归并排序 、插入排序

    不稳定排序: 选择排序,快速排序,堆排序;二叉树排序

    最后说一个题目 (主要也是归并的运用)

    1.有n个不相等,且元素个数小雨1000000请用一种最快的方式排序

      解决方式有很多种,但是题目强调是最快,就是要循环的次数比较小

    用比特位在完全二叉树下,讲每个数组下标来表示元素,同事让数组最小。

    所以使用char类型的数组,或者更小的bit数组

    char b[1000000] = {}

    假设  a []=  [6,3,1,7];

    b为b[]的下标  即b[]= [0,1,2,3,4,5,6,7,8,......]

    对比a[]与b[]

    得到[0,1,0,1,0,0,1,1,0,.....],

    得到新的b下标对应数组[1,3,6,7] 就是所求的的结果

    相关文章

      网友评论

        本文标题:iOS学习笔记--归并排序

        本文链接:https://www.haomeiwen.com/subject/rvrnkxtx.html