冒泡排序,选择排序,插入排序

一、冒泡排序

核心思想
冒泡排序是从后往前扫,通过与相邻元素的比较和交换,把小的数交换到最前面。即使大的往下沉,而小的往上浮。因为这个过程类似于水泡向上升一样,因此被命名为冒泡排序。
时间复杂度
从算法思想可知,冒泡排序需要两个循环来控制遍历,也就是需要n * n趟才能判断、交换完成。所以冒泡排序的时间复杂度为O ( n2 )。
OC版代码如下:


// 冒泡排序法
+ (NSArray *)bubbleSortingWithArray:(NSArray *)array{
    NSMutableArray *arrayM = [array mutableCopy];
    BOOL isUnsorted = YES;
    // 只需要 n-1 趟
    for (NSInteger i = 0; i < arrayM.count - 1 || isUnsorted; ++i) {        
        isUnsorted = NO;
        // 经过第i趟,下标为i的元素已经比后面的元素都要小
        for (NSInteger j = arrayM.count - 1; j > i; --j) {  
            // 比较相邻的两元素 
            if ([arrayM[j] intValue] < [arrayM[j - 1] intValue]) {        
                // 把小的往前移 
                [arrayM exchangeObjectAtIndex:j withObjectAtIndex:j - 1];   
                isUnsorted = YES;
            }
        }
    }
    return [arrayM copy];
}
//输出结果:
//Nums: 24 13 26 5 7 15
//Nums: 24 13 5 26 7 15
//Nums: 24 5 13 26 7 15
//Nums: 5 24 13 26 7 15
//Nums: 5 24 13 7 26 15
//Nums: 5 24 7 13 26 15
//Nums: 5 7 24 13 26 15
//Nums: 5 7 24 13 15 26
//Nums: 5 7 13 24 15 26

冒泡排序动画见 我的Demo

二、选择排序

算法思想
每一趟从前往后查找出值最小的索引(下标),最后通过比较是否需要交换。每一趟都将最小的元素交换到最前面。这和冒泡排序有点类似,都是在一次排序后把最小的元素放到最前面。但是过程不同,冒泡排序是通过相邻的比较和交换。而选择排序是通过对整体的选择。
时间复杂度
要两层循环才能排序完成。所以,选择排序的时间复杂度为O ( n2 )。
OC版代码如下:

// 选择排序法
+ (NSArray *)selectSortingWithArray:(NSArray *)array{
    NSMutableArray *arrayM = [array mutableCopy];
    NSInteger minNumIdx;
    // 只需要 n-1 趟
    for (NSInteger i = 0; i < arrayM.count - 1; ++i) { 
        // 先假设剩下元素中的第一个是最小的 
        minNumIdx = i;                                                  
        for (NSInteger j = i + 1; j < arrayM.count; ++j) {
            // 从前往后,将每个元素与最小的那个比较
            if ([arrayM[j] intValue] < [arrayM[minNumIdx] intValue]) {  
                // 如果某元素比minNumIdx位置更小,更新minNumIdx
                minNumIdx = j;                                          
            }
        }

        // 如果minNumIdx与i不等,说明有比i位置更小的,则交换两者
        if (minNumIdx != i) {                                           
            [arrayM exchangeObjectAtIndex:i withObjectAtIndex:minNumIdx];
        }
    }
    return [arrayM copy];
}
//输出结果:
//Nums: 1 17 29 13 9 21
//Nums: 1 9 29 13 17 21
//Nums: 1 9 13 29 17 21
//Nums: 1 9 13 17 29 21
//Nums: 1 9 13 17 21 29

三、插入排序

本文只介绍直接插入排序
算法思想:
对于每个未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
其过程大概是这样的:
• 第一个元素就认为是有序的
• 从第二个元素起,判断是否大于前一个元素(即已排序序列的最后一个元素)。若是大于,表示已经有序,不用移动,否则将已经有序的序列所有比它大的元素都向后移动一个位置
• 依此类推,直到所有元素已经有序。
时间复杂度
需要到两层循环来处理,外层循环用于跑多少趟,而内层循环用于移动元素位置,因此时间复杂度仍为 O ( n2 )。
OC版代码如下:

// 直接排序排序法
+ (NSArray *)directInsertSortingWithArray:(NSArray *)array{
    NSMutableArray *arrayM = [array mutableCopy];
    // 只需要 n-1 趟,假设第一个元素是有序的
    for (NSInteger i = 1; i <= arrayM.count - 1; ++i) {  
        // 如果某元素比前面已排序的数组中最后(最大)的元素要小,则需要将该元素插入其中 
        if ([arrayM[i] intValue] < [arrayM[i - 1] intValue]) {
            // 记录要插入的元素的值 
            NSInteger numNeedInserted = [arrayM[i] intValue];           

            NSInteger j;
            for (j = i; j > 0 && [arrayM[j - 1] intValue] > numNeedInserted; --j) {
                // 在已排序的数组中,从后往前,只要比要插入的元素的值大,就向后移动一位
                arrayM[j] = arrayM[j - 1];                              
            }

            // 将要插入的元素插入到遇到的第一个比它小的元素的后面,如果没有,则插入到最前面
            arrayM[j] = @(numNeedInserted);                             
        }

    }
    return [arrayM copy];
}

//输出结果:
//Nums: 24 21 23 17 2 12
//Nums: 21 24 23 17 2 12
//Nums: 21 23 24 17 2 12
//Nums: 17 21 23 24 2 12
//Nums: 2 17 21 23 24 12
//Nums: 2 12 17 21 23 24

你可能感兴趣的:(冒泡排序,插入排序,选择排序)