《数据结构与算法》之排序

《数据结构与算法》之链表
《数据结构与算法》之链栈
《数据结构与算法》之队列
《数据结构与算法》之二分查找
《数据结构与算法》之二叉树

如果你是一名程序员,或多或少你都了解过、听说过排序。在项目中我们也会经常用到排序,排序非常重要,现在我在这里分享一些经典的排序算法。
先附上demo地址

冒泡排序

    /// 冒泡排序
    /// - Parameter array: 数组
    class func bubbleSort(array: inout Array<Int>) {
        for i in 0 ..< array.count {
            var end = true
            for j in 0 ..< array.count - i - 1 {
                if array[j] > array[j + 1] {
                    let temp = array[j]
                    array[j] = array[j + 1]
                    array[j + 1] = temp
                    end = false
                }
            }
            
            if end {
                break
            }
        }
        
    }

时间复杂度分析
最好情况下,要排序的数据已经是有序的了,我们只需要进行一次冒泡操作,就可以结束了,所以最好情况时间复杂度是 O(n)。而最坏的情况是,要排序的数据刚好是倒序排列的,我们需要进行 n 次冒泡操作,所以最坏情况时间复杂度为 O( n 2 n^2 n2)。平均时间复杂度也是 O( n 2 n^2 n2)。

插入排序

    /// 插入排序
    /// - Parameter array: 数组
    class func insertionSort(array: inout Array<Int>) {
        for i in 1 ..< array.count {
            //获取基准值
            let value = array[i]
            var j = i - 1; // 查找插入的位置
            while j >= 0 {
                if array[j] > value {
                    array[j+1] = array[j]
                }else {
                    break
                }
                j -= 1
            }
            //把基准值插入合适的位置
            array[j+1] = value;
        }
    }

时间复杂度分析
如果要排序的数据已经是有序的,我们并不需要搬移任何数据。所以这种情况下,最好时间复杂度为 O(n)。如果数组是倒序的,每次插入都相当于在数组的第一个位置插入新的数据,所以需要移动大量的数据,所以最坏情况时间复杂度为 O( n 2 n^2 n2)。平均时间复杂度也是 O( n 2 n^2 n2)。

归并排序

    /// 归并排序
    /// - Parameters:
    ///   - array: 数组
    ///   - startIdx: 开始坐标
    ///   - endIdx: 结束坐标
    class func mergeSort(array: inout Array<Int>, startIdx: Int, endIdx: Int) {
        if array.count == 0 || startIdx >= endIdx {
            return
        }
        
        let midIdx = (startIdx + endIdx) / 2
        self.mergeSort(array: &array, startIdx: startIdx, endIdx: midIdx)
        self.mergeSort(array: &array, startIdx: midIdx + 1, endIdx: endIdx)
        self.merge(array: &array, startIdx: startIdx, midIdx: midIdx, endIdx: endIdx)
    }
    
    /// 数组排序
    class func merge(array: inout Array<Int>, startIdx: Int, midIdx: Int, endIdx: Int) {
        //创建一个临时数组
        var tempArray = Array<Int>.init()
        var i = startIdx  // 第1个有序区的起始索引
        var j = midIdx + 1 // 第2个有序区的起始索引
        
        while i <= midIdx && j <= endIdx {
            //把小的值加到临时数组前面
            if array[i] < array[j] {
                tempArray.append(array[i])
                i += 1
            }else {
                tempArray.append(array[j])
                j += 1
            }
            
        }
        
        while i <= midIdx {
            // 把第1个有序区剩余的数据加入到临时数组中
            tempArray.append(array[i])
            i += 1
        }
        
        while j <= endIdx {
            // 把第2个有序区剩余的数据加入到临时数组中
            tempArray.append(array[j])
            j += 1
        }
        
        // 将排序后的元素,全部都整合到数组array中
        for (idx, value) in tempArray.enumerated() {
            array[startIdx + idx] = value
        }
    }

归并排序时间复杂度为O(nlogn),归并排序不是原地排序算法,需要借助额外的存储空间。空间复杂度为O(n)。

快速排序

/// 快排
    /// - Parameters:
    ///   - array: 数组
    ///   - leftIdx: 左下标
    ///   - rightIdx: 右下标
    class func quickSore(array: inout Array<Int>, leftIdx: Int, rightIdx: Int) {
        if leftIdx >= rightIdx {
            return
        }
        
        var i = leftIdx
        var j = rightIdx
        //记录比较基准数
        let value = array[leftIdx]        
        while i < j {
            //首先从右边j开始查找比基准数小的值
            while i < j && array[j] >= value {
                j -= 1
            }
            //将查找到的小值调换到i的位置
            array[i] = array[j]
            
            //当在右边查找到一个比基准数小的值时,就从i开始往后找比基准数大的值
            while i < j && array[i] <= value {
                i += 1
            }
            //将查找到的大值调换到j的位置
            array[j] = array[i]
        }
        
        //将基准数放到正确位置
        array[i] = value
        
        /**** 递归排序 ***/
        //排序基准数左边的
        self.quickSore(array: &array, leftIdx: leftIdx, rightIdx: i - 1)
        //排序基准数右边的
        self.quickSore(array: &array, leftIdx: i + 1, rightIdx: rightIdx)
    }

大部分情况下的时间复杂度都可以做到 O(nlogn),只有在极端情况下,才会退化到 O( n 2 n^2 n2)。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值