目标:从小到大(或从大到小)对数组进行排序

插入排序算法的步骤

示例:

let numbersArray = [1, 4, 6, 2, 8]
let sortArray = insertionSort(elements: numbersArray)

插入排序

// 这个函数里有两个循环
func insertionSort(elements: [Int]) -> [Int] {
    // 不能直接修改参数elements
    // 所以使用array这个临时变量来进行排序
    var array = elements
    
    // 外部循环遍历数组中的每个元素,注意:索引从1开始
    for i in 1..<array.count {
        // 比较的目标值
        let compareValue = array[i]
        // 临时索引,内循环需要用
        var j = i
        
        // 取出需要比较的值2,这个值跟前边一个比较,如果比前边的小
        // 那么先让当前对应的索引的值,修改为前边的值(比如2与6比较,array[3]=6)
        // 临时变量j同时-1,继续拿着2跟前边的4进行比较
        // 2<4,所以修改当前对应的索引所对应的值为4(array[2]=4)
        // 临时变量j同时-1,
        // 2>1,找到了对应的位置索引,排序array[1] = 2
        
        // 内循环:对应外循环的目标值compareValue,与之前的元素进行比较
        while compareValue < array[j-1] && j > 0{
            array[j] = array[j-1]
            j -= 1
        }
        // [1, 4, 6, 2, 8]
        // 如果目标值(比如4)compareValue > array[j-1](比如1)
        // 那么array[1] = compareValue,直接排序,然后进入下一个外循环,去比较6
        array[j] = compareValue
    }
    return array
}

插入排序的核心:内循环里面是已经排好序的,外循环的目标值插入到内循环的对应位置

外循环的目标值与内循环里面相邻值挨个比较,如果目标值比前一个值大,直接排序,array[j] = compareValue;

如果目标值比前一个值小,那么当前索引所对应的值=前面的值,array[j] = array[j-1],继续对目标值与前面的值比较,重复操作,直到索引为0,停止内循环

性能

最坏情况下插入排序的平均情况性能是 O(n ^ 2) 。 这是因为在这个函数中有两个嵌套循环。 其他排序算法(如快速排序和合并排序)的性能是 O(n log n),在数据量较大时更快

插入排序实际上对排序小数组非常快。 当元素个数为10或更小需要排序的时候,一些标准库会把它们的排序方法从快速排序切换到插入排序。