Swift实现排序算法

本文介绍了如何使用Swift实现三种主要的排序算法:快速排序、归并排序和堆排序。详细讲解了每种排序算法的时间复杂度及实现步骤,包括堆的性质和维护。堆排序部分特别强调了建堆、排序堆和整合的过程,并指出其在面试中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1、快速排序

2、归并排序

3、堆排序

基础知识:

堆的性质:

实现步骤

1、维护堆节点方法

2、建堆

3、排序堆

4、整合


1、快速排序

时间复杂度O( Nlog2N))

1、选择基准点P,大的放在右边,小的放在左边。

2、递归调用左边,右边


func quickSorted (_ nums: inout [Int], _ left: Int, _ right: Int) {
   if left >= right {
        return ;
    }
    var l = left
    var r = right
    let pivot = nums[l]
    while l < r {
        while nums[r] >= pivot && l < r {//以l为基准点就要先从r处先遍历
            r -= 1
        }
        nums[l] = nums[r]//l的位置付给了pivot,所有可以把r的值放在l了
        while nums[l] <= pivot && l < r {
             l += 1
        }
        nums[r] = nums[l]//同理可以把l的位置放在r处,因为r的数字已经放在上一个了处
    }

    // 此时 l 等于中间位置 (可能等于 r)
    nums[l] = pivot //pivot的位置已经a安排好了
    quickSorted(&nums, left, l - 1)
    quickSorted(&nums, l + 1, right)
    
}

2、归并排序

时间复杂度O( N logN)

先分治,再合并

 func mergeSorted(_ nums: inout [Int]) { //先分治,再合并
        let length = nums.count - 1
        var temp = Array<Int>(repeating: 0, count: nums.count) //临时数组
        mergePass(&nums, &temp, 0, length)
    }

    //分治
    func mergePass(_ nums: inout [Int], _ temp: inout [Int], _ left: Int , _ right: Int) {
        if left < right  { //元素数据大于 1
            let mid = (right + left) / 2
            print ("left == :\(left), mid = \(mid), right = \(right) ")

            //递归划分左半区
            mergePass(&nums, &temp, left, mid)
            //递归划分右半区
            mergePass(&nums, &temp, mid + 1, right)
            
            merge(&nums, &temp, left, mid, right)
        }
    }

    //合并已经排序的部分
    func merge(_ nums: inout [Int],  _ temp: inout [Int], _ left:Int, _ mid: Int, _ right: Int ) {
        var lP = left //左半区为合并的元素
        var rP = mid + 1  //右半区为合并的第一个元素
        var pos = left  //临时数组的元素下标

        //合并
        while lP <= mid && rP <= right  {
            if nums[lP] <= nums[rP] {
                temp[pos] = nums[lP]
                pos += 1
                lP += 1
            } else {
               temp[pos] = nums[rP]
                pos += 1
                rP += 1
            }
        }
        // 合并剩余部分
        while lP <= mid {
            temp[pos] = nums[lP]
            pos += 1
            lP += 1
        }
        while rP <= right {
           temp[pos] = nums[rP]
           pos += 1
           rP += 1
        }
       
        //将排序好的序列复制回原数组
        var left = left
        while left <= right {
            nums[left] = temp[left]
            left += 1
        }

    }


3、堆排序

时间复杂度O( N logN)不稳定。

基础知识:

堆:一种特殊的树。 大顶堆: 根节点比 左右子节点大。 小顶堆: 根节点比 左右子节点小

堆的性质:

              1、下标为i 的节点的父节点的下标为:(i-1)/2

              2、下标为i 的父亲节点,左孩子下标为 i*2 + 1

              3、下标为i 的父亲节点,左孩子下标为 i*2 + 2

实现步骤

         1、实现堆节点调整 O(logN)

          2、 建堆  时间复杂度:O(n)

          3、 移除第一个元素。然后调整堆。

          4、 递归3 完成

1、维护堆节点方法

        思路 :1、找到维护点的左右子节点。把最大的放在根节点。

                      2、 如果根与子节点有交互,则需要递归交换,子节点的所有子节点

 //维护堆节点 :nums:堆数组(需要维护), l:堆数组的长度, n:维护的节点在堆数组中的下标. O(logN)
    func heapVerify(_ nums: inout [Int], _ l: Int, _ n: Int) { ///
        var largest = n
        let lSon = 2*n + 1 //堆的子节点在数组中的位置和父亲节点在数组中位置的关系
        let rSon = 2*n + 2
        
        //两次比较找出最大的 三者中最大的数字位置,放在Largest
        if lSon < l && nums[largest] < nums[lSon]  {
            largest = lSon
        }
        if rSon < l && nums[largest] < nums [rSon] {
            largest = rSon
        }
        
        if largest != n {
            nums.swapAt(largest, n)
            heapVerify(&nums, l, largest) //因为交换后的s位置已经放在了 largest里了
        }
    }

2、建堆

    func buildHeap(_ nums: inout [Int]) {
        let n = nums.count 
        var i = n/2 - 1 //从堆的最后一个有子节点的元素开始。即数组最后一个元素n-1 => 的父节点为:((n-1)-1)/2
        while i >= 0 {
            heapVerify(&nums, n, i)
            i -= 1
        }
        print("建堆为:\(nums)")
    }

3、排序堆

    //排序堆
    func sortHeap(_ nums: inout [Int] ) {
        var i = nums.count - 1
        while i > 0 {
            nums.swapAt(i, 0) //大顶堆最大元素在堆顶。把最大元素移到堆尾部
            heapVerify(&nums, i, 0)  //维护堆除去堆底(最大)元素后的,堆顶元素的性质
            i -= 1
        }
    }
    

4、整合

其实2、3 可以放在一起。

 func heapSorted(_ nums: inout [Int]) {
        buildHeap(&nums)
        sortHeap(&nums)
    }

        面试中考到的频率还是比较高的,也是easy的算法题。以上三种排序必须毫无卡顿,毫无差错的撸出来才行。每天没事的时候写一下练个手,可以看最快多长时间写完成。与君共勉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值