排序算法

188 阅读5分钟

本文会用Swift 实现一些常见的排序算法

1、插入排序

直接插入排序

把待排序的数据按其大小逐个插入到一个已经排好序的有序序列中,直到所有插入完为止,得到一个新的有序序列。

 func insert_sort<T: Comparable>(array: inout [T]) -> [T] {
    
    for i in 1 ..< array.count {
        
        for j in (0 ... i-1).reversed() {
            
            if array[i] > array[j] {
                
                array.insert(array[i], at: j+1)
                array.remove(at: i+1)
                break
                
            } else {
                continue
            }
        }
    }
    return array
}

var array: [Int] = [0,2,4,1,9,5,7,8,3,6]
insert_sort(array: &array)
print(array)

折半插入排序

折半插入排序是直接插入排序的升级。插入一个已经排好顺序的序列的中,使用折半查找即可。在时间复杂度上“折半插入排序”仍然是O(n2),减少了比较次数,但是移动次数没变。

/// 查找要插入的Index
func findIndex<T: Comparable>(array: [T], fromHight: Int, value: T) -> Int {
    
    var low: Int = 0
    var hight: Int = fromHight
    var mid: Int = 0
    
    while hight >= low {
        mid = (low + hight)/2 
        
        if value >= array[mid] {
            low = mid + 1
        } else {
            hight = mid - 1
        }
    }
    return hight + 1
}

func insert_sort<T: Comparable>(array: inout [T]) -> [T] {
    
    for i in 1 ..< array.count {
        
        let index = findIndex(array: array, fromHight: i-1, value: array[i])
        array.insert(array[i], at: index)
        array.remove(at: i+1)
    }
    return array
}

var array: [Int] = [0,2,4,1,9,5,7,8,3,6]
insert_sort(array: &array)
print(array)

插入排序-希尔排序

待更

2、冒泡排序

最容易理解,也是最笨的排序。

func bubble_sort<T: Comparable>(array: inout [T]) {
    
    for i in 0 ..< array.count - 1 {
    
        for j in 0 ..< array.count - i - 1 {
        
            if array[j] > array[j + 1] {
                (array[j], array[j + 1]) = (array[j + 1], array[j])                
            }
        }
    }
}

var array: [Int] = [0,2,4,1,9,5,7,8,3,6]
bubble_sort(array: &array)
print(array)

3、快速排序

快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。 步骤为: 从数列中挑出一个元素,称为"基准"(pivot), 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为**分区(partition)**操作。 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。 递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。from wiki

func quick_sort<T: Comparable>(array: inout [T], left: Int, right: Int) {
    
    // 如果左边大于右边,说明已经排序完成了一个子数组
    guard left < right else {
        return
    }
    
    var i = left
    var j = right
    // key 有“保存临时值“和”标识“的作用
    let key = array[left]
    
    // 在当前数组内进行查询
    while i < j {
    
        /* 从右向左查找 结束条件,1:找到一个小于key值 2:没有符合条件1的,且j减小到小于或者等于i */
        while i < j && key <= array[j] {
            j = j - 1
        }
        array[i] = array[j]
        
        /* 从左向右查找 结束条件,1:找到一个大于key值 2:没有符合条件1的,且i增加到到大于或者等于j */
        while i < j && key >= array[i] {
            i = i + 1
        }
        array[j] = array[i]
        
    }
    
    // 最后完成替换 把key值复制给 i
    array[i] = key
    
    // 递归
    quick_sort(array: &array, left: left, right: i-1)
    quick_sort(array: &array, left: i+1, right: right)
}

var array: [Int] = [0,2,4,1,9,5,7,8,3,6]
quick_sort(array: &array, left: 0, right: array.count - 1)
print(array)

4、选择排序

简单选择排序

func select_sort<T: Comparable>(array: inout [T]) -> [T] {

    for i in 0 ..< array.count {
    
        var minInedx = i

        for j in i ..< array.count {
        
            if array[j] < array[minInedx] {
                minInedx = j
            }
            
        }
        array.insert(array[minInedx], at: i)
        array.remove(at: minInedx + 1)
    }
    return array
}

var array: [Int] = [0,2,4,1,9,5,7,8,3,6]
select_sort(array: &array)
print(array)

二元选择排序

简单选择排序每次只确定一个元素,二元选择是在一轮判断中确定最大值和最小值。

func select_sort<T: Comparable>(array: inout [T]) -> [T] {

    for i in 0 ..< array.count {
    
        var minIndex = i
        var maxIndex = i

        for j in i ..< array.count {
        
            if array[j] < array[minIndex] {
                minIndex = j
            }
            if array[j] > array[maxIndex] {
                maxIndex = j
            }
        }
        
        array.insert(array[minIndex], at: i)
        array.remove(at: minIndex + 1)
        array.append(array[maxIndex])
        array.remove(at: maxIndex)
    }
    return array
}

var array: [Int] = [0,2,4,1,9,5,7,8,3,6]
select_sort(array: &array)
print(array)

5、归并排序

采用的也是分治的思想,地轨完成排序。 原理就是 数组拆分成两个有序的数组然后在进行合并,如果某一个不是有序则重复上次步骤再次拆分直到数组只有一个元素我们可以认为其是有序的,然后递归合并。

完正的过程:无序数组 -> 拆分 -> 排序合并 -> 有序数组

func merge_action<T: Comparable>(array: inout [T], head: Int, mid: Int, tail: Int) {
    var temp: [T] = []
    var i = head
    var j = mid + 1

    while i <= mid && j <= tail {
        if array[i] <= array[j] {
            temp.append(array[i++])
        } else {
            temp.append(array[j++])
        }
    }
    
    while i <= mid {
        temp.append(array[i++])
    }
    
    while j <= tail {
        temp.append(array[j++])
    }

    for t in 0 ..< temp.count {
        array[head + t] = temp[t]
    }
}


func merge_sort<T: Comparable>(array: inout [T], head: Int, tail: Int) {
    guard head < tail else {
        return
    }
    let mid = (head + tail) / 2

    merge_sort(array: &array, head: head, tail: mid)
    merge_sort(array: &array, head: mid+1, tail: tail)
    merge_action(array: &array, head: head, mid: mid, tail: tail)
}

var array: [Int] = [0,2,4,1,9,5,7,8,3,6]
merge_sort(array: &array, head: 0, tail: 9)
print(array)

简单的写了几个排序,其他的排序会慢慢实现以下。

未完待续~