Swift 实现七大排序算法

207 阅读1分钟

冒泡排序

//冒泡排序  外圈决定内圈循环趟数  比对内圈相邻的两个数的大小  换位置

func bubbleSort(arr:inout [Int]){
    guard arr.count > 1 else{
         return
    }
    for i in 0..<arr.count-1{
        for j in 0..<arr.count-1-i{
            if arr[j]>arr[j+1]{
                let temp = arr[j]
                arr[j] = arr[j+1]
                arr[j+1] = temp
            }
        }
    }
}

选择排序

//选择排序 首先要搞个最小值,然后内圈比对改变最小索引  外圈替换
func selectSort(arr:inout [Int]){
    guard arr.count > 1 else{
         return
    }
    for i in 0..<arr.count-1{
         var min = i
         
        for j in i+1..<arr.count{
            
            if arr[j] < arr[min]{
               min = j
            }
            
        }
        let temp = arr[i]
        arr[i] = arr[min]
        arr[min] = temp
    
    }
    
    
}

插入排序

//插入排序 内层使用 while 循环
func insertSort(arr:inout [Int]){
    guard arr.count > 1 else{
         return
    }
    for i in 1..<arr.count{
        var j = i
        let temp  = arr[i]
        while j > 0 && temp < arr[j-1] {
            arr[j] = arr[j-1]
            j -= 1
        }
        arr[j] = temp
    }


}

希尔排序

func shellSort(arr:inout [Int]){
    guard arr.count > 1 else{
         return
    }

    let n = arr.count
    var h = 1
    while h < n / 3 {//动态定义间隔序列
        h = 3 * h + 1
    }
    while h > 0 {
        
        for i in h..<n{
            var j = i
            let temp = arr[i]
            while j >= h && temp < arr[j-h] {
                arr[j] = arr[j-h]
                j -= h
            }
            arr[j] = temp
        }
       h /= 3
    }
        
}

归并排序

//归并排序  分治 自上而下的递归
func mergeSort(arr: [Int])->[Int]{
    guard arr.count > 1 else {
        return arr
    }
    let mid = arr.count/2
    let leftArr = mergeSort(arr: [Int](arr[0..<mid]))
    let rightArr = mergeSort(arr: [Int](arr[mid..<arr.count]))
    return merge(leftArr: leftArr, rightArr: rightArr)
}
func merge(leftArr:[Int],rightArr:[Int])->[Int]{
     var left = 0
     var right = 0
     
     var orderArr = [Int]()
    
    while left < leftArr.count && right < rightArr.count {
        if leftArr[left] < rightArr[right]{
            orderArr.append(leftArr[left])
            left += 1
        }else if leftArr[left] > rightArr[right]{
            orderArr.append(rightArr[right])
            right += 1
        }else{
            orderArr.append(leftArr[left])
            left += 1
            orderArr.append(rightArr[right])
            right += 1
        }
        
    }
    while left < leftArr.count {
        orderArr.append(leftArr[left])
        left += 1
    }
    while right < rightArr.count {
        orderArr.append(rightArr[right])
        right += 1

    }
    
    
    return orderArr
}

快速排序

//快排 和归并有点像 都是分而治之的方式进行排序 和冒泡一样属于交换排序
func quickSort(arr: inout [Int],_ low:Int,_ high:Int){
    guard arr.count > 1 else {
        return
    }
    
    guard low < high else {
        return
    }
    
    var i = low,j = high
    
    var p = arr[i]
    
    while i < j {
            
        while i < j && arr[j] >= p{
            j -= 1
        }
        arr[i] = arr[j]
        
        while i < j && arr[i] <= p {
            i += 1
        }
        arr[j] = arr[i]
    }
    p = arr[i]
    
    quickSort(arr: &arr, low, i-1)
    quickSort(arr: &arr, i+1, high)
    
}

堆排序

//堆排序 堆是一个近似完全二叉树  满足堆积性质  构建大顶堆排序

func heapSort(arr:inout [Int]){
    
    var i = arr.count/2 - 1
    //从二叉树的一边的最后一个结点开始

    while i>=0 {
        //从第一个非叶子结点从下至上,从右至左调整结构
        adjustHeap(arr: &arr, i, arr.count)
        i -= 1
    }
    
    var j = arr.count - 1
    //2、调整堆结构+交换堆顶元素与末尾元素

    while j >= 1 {
        //将堆顶元素与末尾元素进行交换
    
        arr.swapAt(0, j)
        //重新对堆进行调整
        adjustHeap(arr: &arr, 0, j)
        j -= 1
    }
    
}
//调整大顶堆(仅是调整过程,建立在大顶堆以构建的基础上)

func adjustHeap(arr : inout [Int],_ index:Int,_ length:Int){
    
    var i = index
    //取出当前元素i

    let temp = arr[i]
      
    var k = 2 * i + 1
    //从i结点的左子节点开始,也就是2i+1处开始

    while k < length {
        //如果左子节点小于右子节点,k指向右子节点

        if k+1 < length && arr[k] < arr[k+1]{
            k += 1
        }
        
        //如果子节点大于父结点,将子节点值赋给父结点,不用进行交换
        if arr[k] > temp{
            arr[i] = arr[k]
            //记录当前结点
            i = k
        }else{
            break
        }
        //下一个结点
        k = k*2+1

        
    }
    //将tmp值放到最终的位置
       arr[i] = temp

}