常见的几种排序算法,附OC实现

626 阅读5分钟

冒泡排序

这个可能是大家最熟悉的一种排序算法了,看下排序实现,方法是相邻的两个比较,大的后移后者小的后移(取决于排序方式),a[0]和a[1]比较,6 > 2,交换a[0]和a[1], 然后a[1]和a[2]比较,6 > 3,交换a[1]和a[2],这样一步步把最大的移到最后一位

运算/角标 0 1 2 3 4 5
初始 6 2 3 5 4 1
一次 2 3 5 4 1 6
二次 2 3 4 1 5 6
三次 2 3 1 4 5 6
四次 2 1 3 4 5 6
五次 1 2 3 4 5 6
六次 1 2 3 4 5 6

OC 代码实现

  for (int i = 0; i < mArr.count; i ++) {
        for (int j = 0; j < mArr.count - i - 1; j ++) {
            // 这里不能直接 > 比较  需要转int后比较
                if ([mArr[j] intValue] > [mArr[j + 1] intValue]) {
                    
                    NSNumber *temp = mArr[j];
                    mArr[j] = mArr[j + 1];
                    mArr[j + 1] = temp;
                }
           
        }
    }

插入排序

将要排序的数组分为两个区间,已排序和未排序,取未排序区间的元素,插入到已排序区间的合适位置

运算/角标 0 1 2 3 4 5
初始 6 2 3 5 4 1
一次 6 2 3 5 4 1
二次 2 6 3 5 4 1
三次 2 3 6 5 4 1
四次 2 3 5 6 4 1
五次 2 3 4 5 6 1
六次 1 2 3 4 5 6

OC 代码实现

 // 外层循环控制有序区间
    for (int i = 0; i < mArr.count - 1; i ++) {
        // 内层循环插入
        for (int j = 0; j <= i; j ++) {
            if ([mArr[i + 1] intValue] < [mArr[j] intValue]) {
                NSNumber *temp = mArr[j];
                mArr[j] = mArr[i + 1];
                mArr[i + 1] = temp;
            }
        }
    }

选择排序

和插入排序一样,将要排序的数组分为两个区间,已排序和未排序,取未排序区间中的最小元素(升序排列时),插入到已排序区间的末尾

运算/角标 0 1 2 3 4 5
初始 6 2 3 5 4 1
一次 1 6 2 3 5 4
二次 1 2 6 3 5 4
三次 1 2 3 6 5 4
四次 1 2 3 4 6 5
五次 1 2 3 4 5 6
六次 1 2 3 4 5 6

OC 代码实现

    // 外层循环控制已排序区间
    for (int i = 0; i < mArr.count - 1; i ++) {
        // 内层循环遍历未排序区间,将最小的(最大的)移到未排序区间头部
        (此处是每次遇到更小的或更大的就交换,还可写成每次遇到更小或更大的记
        录下来,等最后了再交换,可避免不必要的数据操作)
        for (int j = i; j < mArr.count - 1; j ++) {
            if ([mArr[i] intValue] > [mArr[j + 1] intValue]) {
                NSNumber *temp = mArr[i];
                mArr[i] = mArr[j + 1];
                mArr[j + 1] = temp;
            }
        }
    }

归并排序

归并排序的思想就是拆分,20个元素排序问题可以拆分成两个10元素的排序问题,每个10元素的排序问题又可以拆分成两个5元素的排序问题,以此类推,最后就会有若干个有序元素集合,然后一一合并就可以得到最终结果了,完整代码在文章末尾链接

OC 代码实现

 if (arr.count > 2) {
    
            NSMutableArray *arr1 = [[NSMutableArray alloc] init];
            NSMutableArray *arr2 = [[NSMutableArray alloc] init];

        // 分割
            for (int i = 0; i < arr.count; i ++) {
                if (i < floor(arr.count / 2)) {
                    [arr1 addObject:arr[i]];
                } else {
                    [arr2 addObject:arr[i]];
                }
            }
        // 递归操作,合并有序数组
        
      return  [self mergeArr:[self mergerSort:arr1] withArr:[self mergerSort:arr2]];
        
      
        
    }
    //  递归终止条件为arr.count <= 2,拆分到最后了进行处理
    else {
        
        // 只剩下两个时排序
        if (arr.count == 2) {
            
            NSMutableArray *resultArr = [[NSMutableArray alloc] init];
            
            if ([arr[0] intValue] > [arr[1] intValue]) {
                [resultArr addObject:arr[1]];
                [resultArr addObject:arr[0]];
            } else {
                [resultArr addObject:arr[0]];
                [resultArr addObject:arr[1]];
            }
            
            return [resultArr copy];
            
        } else {
            return arr;
        }
    }

快速排序

快速排序的思想也是拆分,取数组中的一个元素a作为参考值,将所有小于a的元素放在左面,大于a的元素放在右面,这样,a在数组中的位置就是排序完成后应该在的位置,这样数组就被分为小于a,a,大于a三个部分,然后对小于a的部分,大于a的部分做同样的操作,以此类推,最后所有的元素都将被放在正确的位置上,这样就完成了快速排序

OC 代码实现 这个实现方法不理解的话可以多看几遍,自己画一下图,看数组中的元素是怎么移动的

 + (void )quickSort:(NSMutableArray *)array leftIndex:(NSInteger)leftIndex rightIndex:(NSInteger)rightIndex {
    if (leftIndex >= rightIndex) {//如果数组长度为0或1时返回
        return ;
    }
    
    NSInteger i = leftIndex;
    NSInteger j = rightIndex;
    //记录比较基准数
    NSInteger key = [array[i] integerValue];
    
    while (i < j) {
        /**** 首先从右边j开始查找比基准数小的值 ***/
        while (i < j && [array[j] integerValue] >= key) {//如果比基准数大,继续查找
            j--;
        }
        //如果比基准数小,则将查找到的小值调换到i的位置
        array[i] = array[j];
        
        /**** 当在右边查找到一个比基准数小的值时,就从i开始往后找比基准数大的值 ***/
        while (i < j && [array[i] integerValue] <= key) {//如果比基准数小,继续查找
            i++;
        }
        //如果比基准数大,则将查找到的大值调换到j的位置
        array[j] = array[i];
        
    }
    
    //将基准数放到正确位置
    array[i] = @(key);
    
    /**** 递归排序 ***/
    //排序基准数左边的
    [self quickSort:array leftIndex:leftIndex rightIndex:i - 1];
    //排序基准数右边的
    [self quickSort:array leftIndex:i + 1 rightIndex:rightIndex];
}

以上就是几种常见的排序算法,实现方法有待改进,后续会继续更新,完整代码在github