美文网首页
算法导论第六章-堆排序(三)&(四)

算法导论第六章-堆排序(三)&(四)

作者: Ahungrynoob | 来源:发表于2018-06-03 22:18 被阅读0次

    6.3-1说明BUILD-MAX-HEAP在数组A=[5,3,17,10,84,19,6,22,9]上的操作过程
    答:废话不多说,直接上代码,这次在接口上添加了一个BuildMaxHeap函数,基于上一节的MaxHeapify函数,美滋滋。

    package main
    
    import (
        "fmt"
    )
    
    type heapify interface {
        LEFT(i int) int
        RIGHT(i int) int
        MaxHeapify(i int)
        BuildMaxHeap()
    }
    
    type maxHeap []int
    
    func (A maxHeap) LEFT(i int) int {
        return i << 1
    }
    
    func (A maxHeap) RIGHT(i int) int {
        return (i<<1 + 1)
    }
    
    func (A maxHeap) MaxHeapify(i int) {
        largest := i
        l := A.LEFT(i)
        r := A.RIGHT(i)
        if l <= len(A) && A[l-1] > A[i-1] {
            largest = l
        }
        if r <= len(A) && A[r-1] > A[largest-1] {
            largest = r
        }
        if largest != i {
            A[largest-1], A[i-1] = A[i-1], A[largest-1]
            A.MaxHeapify(largest)
        }
    }
    
    func (A maxHeap) BuildMaxHeap() {
        for i := len(A) / 2; i > 0; i-- {
            A.MaxHeapify(i)
        }
    }
    
    func main() {
        a := maxHeap{5, 3, 17, 10, 84, 19, 6, 22, 9}
        var h heapify = a
        h.BuildMaxHeap()
        fmt.Println(h)
    }
    

    打印出来的结果:[84 22 19 10 3 17 6 5 9]

    对于BUILD-MAX-HEAP中第二行的循环控制变量i来说,为什么我们要求它是从[A.length/2]到1递减,而不是从1到[A.length/2]递增呢?
    答:因为这样才能保证对于每个子堆的根元素,它的子堆是最大堆。

    6.3-3 证明:对于任一包含n个元素的堆中,至多有[n/2^(h+1)]个高度为h的结点
    答:利用数学归纳法。当h=0时,有n/2个结点,成立。
    当h=k时,假设有[n/2^(k+1)]个高度为k的结点成立。
    则当h=k+1时,对于一棵二叉树来说则有[n/2(k+1)]/2个结点,即[n/2(k+2)]个结点,结论成立。

    6.4-1 说明HEAPSORT在数组A=[5,13,2,25,7,17,20,8,4]上的操作过程
    答:老规矩:直接上代码。

    package main
    
    import (
        "fmt"
    )
    
    type heapify interface {
        LEFT(i int) int
        RIGHT(i int) int
        MaxHeapify(i int, heapSize int)
        BuildMaxHeap()
        HeapSort()
    }
    
    type maxHeap []int
    
    func (A maxHeap) LEFT(i int) int {
        return i << 1
    }
    
    func (A maxHeap) RIGHT(i int) int {
        return (i<<1 + 1)
    }
    
    func (A maxHeap) MaxHeapify(i int, heapSize int) {
        largest := i
        l := A.LEFT(i)
        r := A.RIGHT(i)
        if l <= heapSize && A[l-1] > A[i-1] {
            largest = l
        }
        if r <= heapSize && A[r-1] > A[largest-1] {
            largest = r
        }
        if largest != i {
            A[largest-1], A[i-1] = A[i-1], A[largest-1]
            A.MaxHeapify(largest, heapSize)
        }
    }
    
    func (A maxHeap) BuildMaxHeap() {
        for i := len(A) / 2; i > 0; i-- {
            A.MaxHeapify(i, len(A))
        }
    }
    
    func (A maxHeap) HeapSort() {
        A.BuildMaxHeap()
        for i := len(A); i >= 1; i-- {
            A[i-1], A[0] = A[0], A[i-1]
            A.MaxHeapify(1, i-1)
        }
    }
    
    func main() {
        a := maxHeap{5, 13, 2, 25, 7, 17, 20, 8, 4}
        var h heapify = a
        h.HeapSort()
        fmt.Println(h)
    }
    

    结果:[2 4 5 7 8 13 17 20 25]

    6.4-3 对于一个按升序排列的包含n个元素的有序数组A来说,HEAPSORT的复杂度是多少?如果A是降序呢?
    答:升序情况下:复杂度为nlgn,和最坏情况没有区别。
    降序情况下:复杂度为依然为nlgn。

    6.4-4 证明在最坏的情况下,HEAPSORT的时间复杂度是nlgn
    答:每次调用BUILD-MAX-HEAP的时间复杂度是O(n),而n-1次调用MAX-HEAPIFY,每次的时间复杂度是O(lgn),所以总的来说时间复杂度为nlgn。

    相关文章

      网友评论

          本文标题:算法导论第六章-堆排序(三)&(四)

          本文链接:https://www.haomeiwen.com/subject/gwyssftx.html