美文网首页
数据结构-排序(OC实现)

数据结构-排序(OC实现)

作者: samstring | 来源:发表于2020-05-21 21:14 被阅读0次

从大类分,排序分为外排序和内排序。内外排序的区别在于是否需要多次从内存外读取数据进行排序。外排序是要多次从外存读取数据到内存。而内排序是一次性读到内存中进行排序。
从算法的稳定性来说,排序分为稳定排序和非稳定排序。非稳定排序是指对于两个相同大小的元素,多次进行排序,其所在位置不一定相同。而稳定排序是指,对于每一个元素,每一次排序后所在的位置都是确定的。
从排序的操作,可以大致如下区分


QQ20200519-210256.png

其中冒泡,简单选择,直接插入都是属于简单算法,相对适用于数量比较少的数组排序,实现也较为简单。
而希尔排序,归并排序,堆排序,快速排序属于改进的排序算法。相对适用于较为多的数组排序,改进的排序算法中,只有归并排序是稳定排序,如果对数组的排序稳定性有要求,建议使用归并排序。

各个算法的时间复习度如下


9-0-3.jpg

下面由简单到困难,去实现几个算法


冒泡排序

中心思想:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止

代码实现

+(NSMutableArray *)bubbleSort:(NSMutableArray *)array withOrderType:(OrderType)orderType{
   BOOL isSwap = YES;//某一次循环是否有交换,如果没有交换,则代表着往后的数组有序,则不用再冒泡替换
   
   
   for (int i = 0; i < array.count-1 && isSwap; i++) {
       isSwap = NO;
       for ( int j = (int)array.count - 1; j > i; j--) {
           //            NSNumber *numberA = array[j];
           //            NSNumber *numberB = array[j-1];
           if(orderType ==  OrderType_Aesc){
               if([array[j] intValue] < [array[j-1] intValue]){
                   [array swapFrom:j toIndex:j-1];
                   isSwap = YES;
               }
               //
           }else if(orderType ==  OrderType_Desc){
               
               if([array[j] intValue] > [array[j-1] intValue]){
                   [array swapFrom:j toIndex:j-1];
                   isSwap = YES;
               }
               
               
           }
       }
   }
   return  array;
}

简单选择排序

中心思想:简单选择排序法(Simple Selection Sort)就是通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1≤i≤n)个记录交换之

代码实现


/// 简单选择排序
///  中心思想:通过n-1次比较,计算出n个个元素中最小或是最大的值,然后放在最前方,就能确保最前方的值最小或是最大
///  如[@39,@434,@1,@34,@32,@9],这个数组,
///  从第一个未排序元素开始,循环比对,计算出最小或是最大的值,然后放到最前方
///  循环上方的操作,就能依次把最大或是最小的数放在最前方
///  对比冒泡排序,减少了交互次数,但是比对次数没有减少
/// @param array 待排序数组
/// @param orderType 排序方式
+(NSMutableArray *)simpleSelectionSort:(NSMutableArray *)array withOrderType:(OrderType)orderType{
    
    for (int i = 0; i < array.count; i++) {
        int minIndex = I;
        for (int j = i+1; j < array.count; j++) {
            //            NSNumber *numberA = array[minIndex];
            //            NSNumber *numberB = array[j];
            if(orderType ==  OrderType_Aesc){
                if([array[minIndex] intValue] > [array[j] intValue]){
                    minIndex = j;
                }
                //
            }else if(orderType ==  OrderType_Desc){
                
                if([array[minIndex] intValue] < [array[j] intValue]){
                    minIndex = j;
                }
                
            }
        }
        if(minIndex != i){
            [array swapFrom:minIndex toIndex:i];
        }
    }
    return array;
}


直接插入排序

中心思想:将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表

代码实现

/// 直接插入排序
/// 中心思想,从小到大排列,如果一个元素A与前方有序数组坐比较,如果元素比前方有序数组小,则有序数组一个一个往后挪,直到数组里面某一个元素B不大于元素A时候,A插入到B后面
/// 如果数组基本有序的时候,这个方案比较有优势,不需要做太多比较和数据交互
/// @param array <#array description#>
/// @param orderType <#orderType description#>
+(NSMutableArray *)stragightInsertionSort:(NSMutableArray *)array withOrderType:(OrderType)orderType{
    
    NSNumber *temp = @0;
    
    for (int i = 1; i < array.count; i++) {
        if(orderType == OrderType_Aesc){
            //从原数组的第二个元素开始,每一个元素和前面的元素的做比较
            if ([array[i] intValue] < [array[i - 1] intValue] ) {
                //如果该元素比前一个元素小,则将值存入temp元素当中,用temp和前面的元素做对比,如果少于前面的元素,前面的元素一个一个往后挪。直到前面的元素不大于temp元素时,则停止挪动元素
                temp = array[I];
                int j;
                
                for ( j = i - 1;   j >= 0 && [array[j] intValue] > [temp intValue] ; j--) {
                    array[j+1]  = array[j];
                }
                
                array[j+1] = temp;
                
            }
        }else if(orderType == OrderType_Desc){
            //从第二个元素开始,
            if ([array[i] intValue] > [array[i - 1] intValue] ) {
                temp = array[I];
                int j;
                for ( j = i - 1;  j >= 0 &&  [array[j] intValue] < [temp intValue] ; j--) {
                    array[j+1]  = array[j];
                }
                
                array[j+1] = temp;
                
            }
        }
    }
    
    return  array;
}

希尔排序

中心思想: 将待排序的数据按照一定的间隔n,将间隔n的元素组成一个子数组,对子数组进行直接插入排序,使子数组有序,
代码实现



/// 希尔排序O(n^(1.3—2))
/// 中心思想:
/// 将待排序的数据按照一定的间隔n,将间隔n的元素组成一个子数组,对子数组进行直接插入排序,使子数组有序,
/// 随着n不断减少,原来待数组越来越接近有序
/// 当n= 1的时候,相当于对整个数组已经有序
/// 如果数组基本有序且数组数量比较少时候,这个方案比较有优势,不需要做太多比较和挪动
/// @param array <#array description#>
/// @param orderType <#orderType description#>
+(NSMutableArray *)shellSort:(NSMutableArray *)array withOrderType:(OrderType)orderType{
    
    NSNumber *temp = @0;
    
    int increment = (int)array.count;
    
    while (increment > 1) {
        increment = increment/3 + 1;
        if(orderType == OrderType_Aesc){
            for (int i = increment ; i < array.count; i++) {
                if ([array[i] intValue] < [array[i - increment] intValue] ) {
                    //如果该元素比前一个元素小,则将值存入temp元素当中,用temp和前面的元素做对比,如果少于前面的元素,前面的元素一个一个往后挪。直到前面的元素不大于temp元素时,则停止挪动元素
                    temp = array[I];
                    int j;
                    
                    for ( j = i - increment;   j >= 0 && [array[j] intValue] > [temp intValue] ; j = j - increment) {
                        array[j+increment]  = array[j];
                    }
                    
                    array[j+increment] = temp;
                    
                }
            }
            
        }else if(orderType == OrderType_Desc){
                   for (int i = increment ; i < array.count; i++) {
                       if ([array[i] intValue] > [array[i - increment] intValue] ) {
                           //如果该元素比前一个元素小,则将值存入temp元素当中,用temp和前面的元素做对比,如果少于前面的元素,前面的元素一个一个往后挪。直到前面的元素不大于temp元素时,则停止挪动元素
                           temp = array[I];
                           int j;
                           
                           for ( j = i - increment;   j >= 0 && [array[j] intValue] < [temp intValue] ; j = j - increment) {
                               array[j+increment]  = array[j];
                           }
                           
                           array[j+increment] = temp;
                           
                       }
                   }
                   
               }
    }
    
    return  array;
}


归并排序

中心思想:分治策略,将问题不断的缩小,
通过将数组不断采用二分法分成子数组,对子数组进行排序,从而实现数组整体有序

代码实现

/// 归并排序
/// 中心思想:分治策略,将问题不断的缩小,
/// 通过将数组不断采用二分法分成子数组,对子数组进行排序,从而实现数组整体有序
/// @param array <#array description#>
/// @param orderType <#orderType description#>
+(NSMutableArray *)mergeSort:(NSMutableArray *)array withOrderType:(OrderType)orderType{
    NSMutableArray *tempArray = [array mutableCopy];
    [SortTool mergeSubSort:array withBegin:0 withEnd:(int)array.count - 1 withTempArray:tempArray  withOrderType:orderType];
    return array;
}

/// 递归对数组进行二分,然后再对子数组进行排序
/// @param array <#array description#>
/// @param beginIndex <#beginIndex description#>
/// @param endIndex <#endIndex description#>
/// @param tempArray <#tempArray description#>
/// @param orderType <#orderType description#>
+(void)mergeSubSort:(NSMutableArray *)array withBegin:(int)beginIndex withEnd:(int)endIndex withTempArray:(NSMutableArray *)tempArray withOrderType:(OrderType)orderType{
    
    if(beginIndex < endIndex){
        int midIndex = (beginIndex + endIndex )/2;
        [SortTool mergeSubSort:array withBegin:beginIndex withEnd:midIndex withTempArray:tempArray withOrderType:orderType];
        [SortTool mergeSubSort:array withBegin:midIndex+1 withEnd:endIndex withTempArray:tempArray withOrderType:orderType];
        [SortTool mergeArray:array withBegin:beginIndex  withEnd:endIndex withTempArray:tempArray withOrderType:orderType];
    }else{
        array[beginIndex] = array[endIndex];
    }
    
    
    
}

///
/// @param array <#array description#>
/// @param beginIndex <#beginIndex description#>
/// @param endIndex <#endIndex description#>
/// @param tempArray <#tempArray description#>
/// @param orderType <#orderType description#>
+(void)mergeArray:(NSMutableArray *)array  withBegin:(int)beginIndex withEnd:(int)endIndex withTempArray:(NSMutableArray *)tempArray withOrderType:(OrderType)orderType{
    //获取中间做表
    int midIndex = (beginIndex+endIndex)/2;
    //比较中间坐标两边的数据,将小的放前面
    int i,j,k;
    for ( i = beginIndex, j = midIndex+1 ,k = i; i <= midIndex && j <= endIndex;k++ ) {
        if(orderType == OrderType_Aesc){
            if([array[i] intValue] < [array[j] intValue]){
                       tempArray[k] = array[I];
                       i = i + 1;
                   }else{
                       tempArray[k] = array[j];
                       j = j + 1;
                   }
        }else{
            if([array[i] intValue] > [array[j] intValue]){
                       tempArray[k] = array[I];
                       i = i + 1;
                   }else{
                       tempArray[k] = array[j];
                       j = j + 1;
                   }
        }
    }
    //如果右边的数据已经全部放入暂存数组,则把左边剩余的放入到暂存数组
    if(i <= midIndex){
        for (int l = 0; l <= midIndex - i; l++,k++) {
            tempArray[k] = array[i+l];
        }
    }
    //如果左边的数据已经全部放入暂存数组,则把右边剩余的放入到暂存数组
    if(j <= endIndex){
        for (int l = 0; l <= endIndex - j; l++,k++) {
            tempArray[k] = array[j+l];
        }
    }
    //将暂存数组排好序的部分替换到需要排序的数组中去
    while (beginIndex <= endIndex) {
        array[beginIndex] = tempArray[beginIndex];
        beginIndex = beginIndex + 1;
    }

    
}
     
     


快速排序

中心思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的

代码实现


/// 中心思想:确定一个中枢值,把按大小把数组拆分成左右两个数组,通过递归,把数组不断拆分,以达到排序的目的
/// @param array <#array description#>
/// @param orderType <#orderType description#>
+(NSMutableArray *)quickSort:(NSMutableArray *)array  withOrderType:(OrderType)orderType{
    [SortTool quickSort:array withBeginIndex:0 withEndIndex:(int)array.count -1 withOrderType:orderType];
    return array;
}

+(void)quickSort:(NSMutableArray *)array withBeginIndex:(int)beginInex withEndIndex:(int)endIndex withOrderType:(OrderType)orderType{
    if(beginInex < endIndex){
        //确定中枢,并按照中枢值分左右两个数组,对左右两个数组排序
        int privot = [SortTool makePivot:array withBeginIndex:beginInex withEndIndex:endIndex withOrderType:orderType];
        [SortTool quickSort:array withBeginIndex:beginInex withEndIndex:privot-1 withOrderType:orderType];
        [SortTool quickSort:array withBeginIndex:privot + 1 withEndIndex:endIndex withOrderType:orderType];
    }
}

+(int)makePivot:(NSMutableArray *)array withBeginIndex:(int)beginInex withEndIndex:(int)endIndex withOrderType:(OrderType)orderType{
    //取第一个值为中枢值,然后从首尾两端循环对比。根据大小把数组放在中枢的两边
    int privotValue = [array[beginInex] intValue];
    while (beginInex < endIndex) {
        
        if(orderType == OrderType_Aesc){
            while(beginInex < endIndex && privotValue <= [array[endIndex] intValue]){
                endIndex = endIndex - 1;
            }
            [array swapFrom:beginInex toIndex:endIndex];
            
            while(beginInex < endIndex && [array[beginInex] intValue] <= privotValue){
                       beginInex = beginInex + 1;
                   }
            [array swapFrom:beginInex toIndex:endIndex];
        }else if(orderType == OrderType_Desc){
            while(beginInex < endIndex && privotValue >= [array[endIndex] intValue]){
                           endIndex = endIndex - 1;
                       }
                       [array swapFrom:beginInex toIndex:endIndex];
                       
                       while(beginInex < endIndex && [array[beginInex] intValue] >= privotValue){
                                  beginInex = beginInex + 1;
                              }
                       [array swapFrom:beginInex toIndex:endIndex];
        }
        
    }
    return beginInex;
}

相关文章

  • 数据结构-排序(OC实现)

    从大类分,排序分为外排序和内排序。内外排序的区别在于是否需要多次从内存外读取数据进行排序。外排序是要多次从外存读取...

  • Objective-C实现常用的4种排序算法

    OC实现的4种排序又来了! 4种排序分别是:快速排序、冒泡排序、选择排序、插入排序,其他的我就不写了,因为OC里的...

  • 数据结构排序复习 OC实现

    一、内部排序和外部排序由于待排序的记录数量不同,使得排序过程中的涉及的存储器不同,可将排序方法分为内部排序和外部排...

  • OC各种算法,排序,查找实现

    二维数组查找数字的OC实现 OC 二分查找的实现 快速排序

  • iOS底层初探

    OC底层实现原理 oc对象以及类的是底层实现 首先,通过数据结构的特性可以猜测类的底层应该是结构体这种数据结构,因...

  • OC 对象的本质

    OC的本质 我们平时写的OC代码的底层都是c/c++代码实现的 OC的面向对象都是基于c/c++的数据结构实现的 ...

  • iOS排序方法集合

    OC_选择排序 OC_冒泡排序 参考原文:排序算法

  • OC对象

    OC的本质 oc代码,底层是由c/c++实现 Objective-C的面向对象都是基于C\C++的数据结构实现的 ...

  • 算法:冒泡排序

    本文内容:1、什么是冒泡排序?2、冒泡排序的 C/OC 实现与算法分析。 算法总目录:算法? 1、什么是冒泡排序?...

  • oc实现选择排序

    话不多说,选择排序就是通过遍历数组找出每次遍历数组的最小元素的下标,然后将其按顺序从第一位依次排列比如一个原始数列...

网友评论

      本文标题:数据结构-排序(OC实现)

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