Golang Standard library Drill-down-heap (container/heap)

Source: Internet
Author: User
Tags pear
This is a creation in Article, where the information may have evolved or changed.








Overview



The heap package provides a heap for any type (implemented. Interface interface) for heap operations. The (minimum) heap is a tree with a "minimum value for each node in its subtree" property.



The smallest element of the tree is the location of its root element, index 0.



Heap is a common method of implementing a priority queue. To create a priority queue, implement a heap interface that has a less method that uses a (negative) priority as the basis for comparison, so that the item with the highest priority of the queue can be removed with a pop by using the push Add item.



This is an explanation in the documentation.






(Container/heap container data structure heap



The implementation of the heap is used in the small Gan , the following is a simple description of the heap



1. Heap Concepts



A heap is a sort of complete binary tree in which the data values of any non-endpoint are not greater than (or not less than) the values of their left child and right child nodes.



The maximum heap and the minimum heap are two forms of a two-fork heap.



  Maximum heap : The key value of the root node is the largest of all heap node key values.



  Minimum heap : The key value of the root node is the smallest of all heap node key values.



2. Heap



The smallest element of the tree is at the root, which is index 0.



Heap operations are provided for any type that implements the heap interface.



Heap is a common method of implementing a priority queue. To create a priority queue, implement a heap interface that has a less method that uses a (negative) priority as the basis for comparison, so that the item with the highest priority of the queue can be removed with a pop by using the push Add item.






Type interface



The kernel in the heap package is the heap. Interface interface, the heap's underlying storage is a tree structure that can be implemented in an array or linked list, and the heap can be built and manipulated on the heap through the heap's functions.



Heap. Interface Interface Source code:


type Interface interface {
	sort.Interface
	Push(x interface{}) // add x as element Len()
	Pop() interface{}   // remove and return element Len() - 1.
}





Sort. Interface Interface Source code


type Interface interface {
	// Len is the number of elements in the collection.
	Len() int
	// Less reports whether the element with
	// index i should sort before the element with index j.
	Less(i, j int) bool
	// Swap swaps the elements with indexes i and j.
	Swap(i, j int)
}


Once these interfaces have been implemented, they can be manipulated by the various functions provided by the heap package to implement a heap.



According to the definition of interface above, it can be seen that this heap structure inherits from sort. Interface, and sort. Interface, you need to implement three methods: Len (), less (), Swap ().



Colleagues also need to implement the heap interface definition of the two methods: Push (x interface{})/Pop () interface{}, so we want to use the heap to define a heap, only need to define the implementation of the five method structure can be.



Attention



The push and pop methods for the interface are called by the heap package, using the heap. Push and Heap.pop to add or remove elements to a heap.






member functions



A few of the most basic heap operation functions are provided in the heap, including Init,fix,push,pop and remove (where up and down functions are non-derived functions). These functions operate on the heap by invoking the methods in the previous implementation interface.



Init


func Init(h Interface)


A heap should be initialized before any heap operations are used. The Accept parameter is for the heap to be implemented. The object for the interface interface.






Fix


func Fix(h Interface, i int)


After modifying the element I, it is more efficient to call this function to fix the heap than to insert a new element after removing the element I.






Push&pop



Push and pop are a pair of standard heap operations, push adds a new element to the Heap, POPs pops up and returns the top element of the heap, while push and pop operations do not break the heap's structure



Remove



Remove the I element from the heap and maintain the constraint of the heap






Example Exercise 1



The code implements a small top heap in which the elements in the heap are rectangular classes, sorted by area size, using slice as the underlying storage. The first is the class definition and the interface implementation, which requires implementing the five interfaces mentioned earlier.


package main

import (
"container / heap"
"fmt"
)

// Define a square structure
type Rectangle struct {
width int
height int
}

//
func (rec * Rectangle) Area () int {
return rec.width * rec.width
}

// define a heap structure
type RectHeap [] Rectangle

// implement the heap.Interface interface
func (rech RectHeap) Len () int {
return len (rech)
}

// implement sort.Iterface
func (rech RectHeap) Swap (i, j int) {
rech [i], rech [j] = rech [j], rech [i]
}
func (rech RectHeap) Less (i, j int) bool {
return rech [i] .Area () <rech [j] .Area ()
}

// implement additional methods defined by the heap.Interface interface
func (rech * RectHeap) Push (h interface {}) {
* rech = append (* rech, h. (Rectangle))
}
func (rech * RectHeap) Pop () (x interface (}) {
n: = len (* rech)
x = (* rech) [n-1] // returns deleted element
* rech = (* rech) [: n-1] // [n: m] does not include the element whose index is m
return x
}

func main () {
hp: = & RectHeap {}
for i: = 2; i <6; i ++ {
* hp = append (* hp, Rectangle (i, i))
}

fmt.Println ("Original slice:", hp)

// Heap operation
heap.Init (hp)
heap.Push (hp, Rectangle {100, 10})
fmt.Println ("top element:", (* hp) [0])
fmt.Println ("Delete and return the last:", heap.Pop (hp)) // last element
fmt.Println ("final slice:", hp)
}


Complete this exercise if you have questions?



Then let's take a look at the source code of CONTAINER/HEAP:



Intercept part of it:


// Push pushes the element x onto the heap. The complexity is
// O(log(n)) where n = h.Len().
//
func Push(h Interface, x interface{}) {
	h.Push(x)
	up(h, h.Len()-1)
}

// Pop removes the minimum element (according to Less) from the heap
// and returns it. The complexity is O(log(n)) where n = h.Len().
// It is equivalent to Remove(h, 0).
//
func Pop(h Interface) interface{} {
	n := h.Len() - 1
	h.Swap(0, n)
	down(h, 0, n)
	return h.Pop()
}


In the call heap. After push (), the program calls the heap object's push () method again, and so does the Pop, but POPs does swap (0, N).




Example Exercise 2-the smallest heap containing int


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

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]
    return x
}

// This example inserts several ints into an IntHeap, checks the minimum,
// and removes them in order of priority.
func Example_intHeap() {
    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("%d ", heap.Pop(h))
    }
    // Output:
    // minimum: 1
    // 1 2 3 5
}


Example Exercise 3-Creating a priority queue with a heap


// This example demonstrates a priority queue built using the heap interface.
package heap_test

import (
    "container/heap"
    "fmt"
)

// An Item is something we manage in a priority queue.
type Item struct {
    value    string // The value of the item; arbitrary.
    priority int    // The priority of the item in the queue.
    // The index is needed by update and is maintained by the heap.Interface methods.
    index int // The index of the item in the heap.
}

// A PriorityQueue implements heap.Interface and holds Items.
type PriorityQueue []*Item

func (pq PriorityQueue) Len() int { return len(pq) }

func (pq PriorityQueue) Less(i, j int) bool {
    // We want Pop to give us the highest, not lowest, priority so we use greater than here.
    return pq[i].priority > pq[j].priority
}

func (pq PriorityQueue) Swap(i, j int) {
    pq[i], pq[j] = pq[j], pq[i]
    pq[i].index = i
    pq[j].index = j
}

func (pq *PriorityQueue) Push(x interface{}) {
    n := len(*pq)
    item := x.(*Item)
    item.index = n
    *pq = append(*pq, item)
}

func (pq *PriorityQueue) Pop() interface{} {
    old := *pq
    n := len(old)
    item := old[n-1]
    item.index = -1 // for safety
    *pq = old[0 : n-1]
    return item
}

// update modifies the priority and value of an Item in the queue.
func (pq *PriorityQueue) update(item *Item, value string, priority int) {
    item.value = value
    item.priority = priority
    heap.Fix(pq, item.index)
}

// This example creates a PriorityQueue with some items, adds and manipulates an item,
// and then removes the items in priority order.
func Example_priorityQueue() {
    // Some items and their priorities.
    items := map[string]int{
        "banana": 3, "apple": 2, "pear": 4,
    }

    // Create a priority queue, put the items in it, and
    // establish the priority queue (heap) invariants.
    pq := make(PriorityQueue, len(items))
    i := 0
    for value, priority := range items {
        pq[i] = &Item{
            value:    value,
            priority: priority,
            index:    i,
        }
        i++
    }
    heap.Init(&pq)

    // Insert a new item and then modify its priority.
    item := &Item{
        value:    "orange",
        priority: 1,
    }
    heap.Push(&pq, item)
    pq.update(item, item.value, 5)

    // Take the items out; they arrive in decreasing priority order.
    for pq.Len() > 0 {
        item := heap.Pop(&pq).(*Item)
        fmt.Printf("%.2d:%s ", item.priority, item.value)
    }
    // Output:
    // 05:orange 04:pear 03:banana 02:apple
}








Finally, if you have questions, why use the heap package to operate, please go to station: https://studygolang.com/articles/3719





Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.