算法笔记之堆排序

71 阅读1分钟

###堆排序

  • 堆排序的执行流程
    1. 对序列原地建堆
    2. 交换堆顶元素和尾元素
    3. 堆元素数量 -1
    4. 把交换到堆顶的元素进行下滤操作
    5. 循环执行 2-4,直至堆中元素只剩一个

原地建堆:

private func heapfiy(){
        var i = (size >> 1) - 1
        while i >= 0 {
            siftDown(indexShape: i)
            i -= 1
        }
    }

元素下滤:

/// 让index位置的元素下滤
        /// - Parameter index: <#index description#>
        private func siftDown(indexShape:Int){
            var index = indexShape
            let element = elements[index]
            let half = size >> 1
            // 第一个叶子节点的索引 == 非叶子节点的数量
            // index < 第一个叶子节点的索引
            // 必须保证index位置是非叶子节点
            while index < half {
                // index的节点有2种情况
                // 1.只有左子节点
                // 2.同时有左右子节点
                
                // 左子节点
                var leftChildIndex = (index << 1) + 1
                var leftChild = elements[leftChildIndex]
                // 右子节点
                let rightChildIndex = (index << 1) + 2
                // 默认左子节点与父节点进行比较
                if rightChildIndex < size && elements[rightChildIndex] > elements[leftChildIndex] {
                    leftChild = elements[rightChildIndex]
                    leftChildIndex = rightChildIndex
                }
                if element > leftChild {
                    break
                }
                // 将子节点存放到index位置
                elements[index] = leftChild
                // 重新设置index
                index = leftChildIndex
            }
            elements[index] = element
        }

交换第0元素位置和末尾值:

private func sort(){
        while size > 1 {
            // 第0个最大值交换到数组最后
            let temp = elements[0]
            elements[0] = elements[size - 1]
            elements[size - 1] = temp
            size -= 1
            // 下滤恢复最大堆性质
            siftDown(indexShape: 0)
        }
    }
  • 选择排序的稳定性

    • 选择排序属于不稳定的排序
  • 选择排序的时间复杂度和空间复杂度

    • 时间复杂度 时间复杂度为O(nlogn)
    • 空间复杂度
      • O(1)
      • 属于原地算法

###堆的概念 TODO:待补充

源码及单元测试:github.com/yukifeng/su…