堆索引示例的说明

时间:2018-11-09 00:50:56

标签: sorting go data-structures heap

此代码摘自Go堆示例(带有我自己添加的打印件)。这是操场。 https://play.golang.org/p/E69SfBIZF5X

大多数事情都是简单明了的,但我无法解决的一件事就是为什么index 0中堆main()上的'minimum'打印会返回值{{1} }(正确的最小值),但是在堆的pop函数中打印4会返回1(请参见输出)。

如果堆的根(最小)总是在1处,为什么n=0在pop函数本身中呢?然后,它似乎可以按降序工作。

有人可以解释这里发生了什么吗?在了解发生了什么之前,我不喜欢实施Pop之类的东西。

n=4

-

// This example demonstrates an integer heap built using the heap interface.
package main

import (
    "container/heap"
    "fmt"
)

// An IntHeap is a min-heap of ints.
type IntHeap []int

func (h IntHeap) Len() int           { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }

func (h *IntHeap) Push(x interface{}) {
    // Push and Pop use pointer receivers because they modify the slice's length,
    // not just its contents.
    *h = append(*h, x.(int))
}

func (h *IntHeap) Pop() interface{} {
    old := *h
    n := len(old)
    x := old[n-1]
    *h = old[0 : n-1]
    fmt.Printf("n: %v\n", n)
    fmt.Printf("x: %v\n", x)
    return x
}

// This example inserts several ints into an IntHeap, checks the minimum,
// and removes them in order of priority.
func main() {
    h := &IntHeap{2, 1, 5}
    heap.Init(h)
    heap.Push(h, 3)
    fmt.Printf("minimum: %d\n", (*h)[0])
    for h.Len() > 0 {
        fmt.Printf("roll: %d\n", (*h)[0])
        fmt.Printf("%d\n", heap.Pop(h))
    }
}

1 个答案:

答案 0 :(得分:1)

如果您知道整个堆结构是正确的(a[n] < a[2*n+1] && a[n] < a[2*n+2],对于所有n范围而言),除了根是错误的,教科书堆算法都提供了一种修复堆的方法O(lg n )时间。当您heap.Pop()一个项目时,几乎可以肯定它(*IntHeap).Swap是第一个和最后一个元素,进行了更多交换以维护堆不变式,然后(*IntHeap).Pop最后一个元素。那就是您在这里看到的。

您还可以使用它来实现heap sort。假设您要尝试对数组int[4]进行排序。切片s int[] = (a, len=4, cap=4),然后:

  1. 如果len(s) == 1,请停止。
  2. 交换s[0]s[len(s)-1]
  3. 将切片缩小一项:s = (array(s), len=len(s)-1, cap=cap(s))
  4. 如果堆混乱,请修复它。
  5. 转到1。

说您的示例以[1、2、5、3]开头。然后:

[1, 2, 5, 3]
[3, 2, 5, 1]  Swap first and last
[3, 2, 5], 1  Shrink slice by one
[2, 3, 5], 1  Correct heap invariant
[5, 3, 2], 1  Swap first and last
[5, 3], 2, 1  Shrink slice by one
[3, 5], 2, 1  Correct heap invariant
[5, 3], 2, 1  Swap first and last
[5], 3, 2, 1  Shrink slice by one
  5, 3, 2, 1  Sorted (descending order)