您的位置:首页 > 其它

堆排序(HeapSort)

2015-09-25 15:52 363 查看

一、相关介绍

堆排序(HeapSort),与归并排序一样,但不同于插入排序的是,堆排序的时间复杂度是O(nlgn),空间复杂度是O(n)。而与插入排序相同,但不同于归并排序的是,堆排序同样具有空间原址性:任何时候都只需要常熟个额外的元素空间存储临时数据。

堆排序引入的算法设计技巧:使用一种我们称为“堆”的数据结构来进行信息管理。堆不仅用于堆排序中,而且它也可以构造一种有效的优先队列。

虽然“堆”这一词源自堆排序,但是目前它已经被引申为“垃圾收集存储机制”,例如在Java和Lisp语言中所定义的。强调一下,这里使用的堆不是垃圾收集存储,而是堆数据结构。



二、定义

堆排序(HeapSort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。



(二叉)堆是一个数组,它可以被看成一个近似的完成二叉树。树上的每一个结点队友数组的一个元素。除了最底层外,该树是完全充满的,而且是从左向右填充。表示堆的数组A包含属性:heapSize表示有多少个堆元素存储在该数组中。也就是说,虽然A[1..A.length]可能存有数据,但只有A[1..A.heapSize]中存放的是堆的有效元素,这里,

0 <= A.heapSize <= A.length

树的根节点是A[0]



三、最大堆和最小堆

二叉堆可以分为两种形式:最大堆和最小堆。在这两种堆中,节点的值都是满足堆的性质,但一些细节定义则有所差异。

在最大堆中,最大堆性质是指除了根以外的所有节点i都要满足:

A[parent(i)] >= A[i]

也就是说,某个节点的值至多与其父结点一样大。因此,堆的最大元素存放在根节点中;并且,在任一子树中,该子树所包含的所有节点的值都不大于该子树根节点的值。

最小堆的组织方式正好相反:最小堆性质是指除了根以外的所有节点i都有

A[parent(i)] <= A[i]

最小堆中的最小元素存放根节点中。






四、源代码

//
//  Heap.swift
//  堆排序
//
//  Created by 阳君 on 14/12/12.
//  Copyright (c) 2014年 六月. All rights reserved.
//

import Foundation

/// 堆排序
class Heap {

    /// 数组
    private var list:[Int] = []
    /// 堆长度
    private var heapSize = 0

    //MARK: 初始化
    init(list:[Int]) {
        self.list = list
    }

    //MARK: 最大堆排序
    func maxSort() -> [Int]{
        self.buildMaxHeap()
        for(var i = self.heapSize - 1; i > 0; i--) {
            self.exchange(i, change: 0)
            self.heapSize--
            self.maxBase(0)
        }
        return self.list
    }

    //MARK: 最小堆排序
    func miniSort() -> [Int]{
        self.buildMiniHeap()
        for(var i = self.heapSize - 1; i > 0; i--) {
            self.exchange(i, change: 0)
            self.heapSize--
            self.miniBase(0)
        }
        return self.list
    }

    // MARK: - 父节点
    private func parent(i:Int) -> Int {
        return (i + 1) / 2 - 1
    }

    // MARK: 左节点
    private func left(i:Int) -> Int {
        return 2 * i + 1
    }

    // MARK: 右边节点
    private func right(i:Int) -> Int {
        return 2 * i + 2
    }

    // MARK: 交换节点
    private func exchange(i:Int, change:Int) {
        let tempI:Int = self.list[i]
        self.list[i] = self.list[change]
        self.list[change] = tempI
    }

    // MARK: - 建立最大堆
    private func buildMaxHeap() {
        self.heapSize = self.list.count
        for(var i = self.list.count / 2; i >= 0; i--) {
            self.maxBase(i)
        }
    }

    // MARK: 最大堆的基础算法
    private func maxBase(i:Int) {
        let l = self.left(i)
        let r = self.right(i)
        var largest = i
        // 找出最大的那个数
        if l < heapSize && self.list[l] > self.list[largest] {
            largest = l
        }
        if r < heapSize && self.list[r] > self.list[largest] {
            largest = r
        }
        // 是非需要改变
        if largest != i {
            self.exchange(i, change: largest)
            self.maxBase(largest)
        }
    }

    // MARK: - 建立最小堆
    private func buildMiniHeap() {
        self.heapSize = self.list.count
        for(var i = self.list.count / 2; i >= 0; i--) {
            self.miniBase(i)
        }
    }

    // MARK: 最小堆的基础算法
    private func miniBase(i:Int) {
        let l = self.left(i)
        let r = self.right(i)
        var largest = i
        // 找出最小的那个数
        if l < self.heapSize && self.list[l] < self.list[largest] {
            largest = l
        }
        if r < self.heapSize && self.list[r] < self.list[largest] {
            largest = r
        }
        // 是非需要改变
        if largest != i {
            self.exchange(i, change: largest)
            self.miniBase(largest)
        }
    }

}




五、测试

1. 测试代码

var list:[Int] = []
for(var i = 0; i < 5; i++) {
    list.append(i)
}
for(var i = -2; i < 6; i++) {
    list.append(i)
}
let heap = Heap(list: list)
println("最大堆排序:\(heap.maxSort())")
println("最小堆排序:\(heap.miniSort())")


2. 结果

最大堆排序:[-2, -1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5]

最小堆排序:[5, 4, 4, 3, 3, 2, 2, 1, 1, 0, 0, -1, -2]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: