利用Go语言维护并测试最小堆

利用Go语言维护并测试最小堆

文章目录

  • 利用Go语言维护并测试最小堆
    • 实验目的
    • 最小堆
    • 测试(gocheck)
    • 完整代码

实验目的

  1. 熟悉 Go 语⾔对结构体数组的操作
  2. 熟悉 Go 语⾔中的函数不同类型的参数传递

最小堆

最小堆就是在二叉堆的基础上,其中任一非终端节点的数据值均不大于其左子节点和右子节点的值

在B站上看到一个演示视频(最大堆),可以参考一下:HERE

最小堆中最重要的实现的两种情况:

  1. down:当某个节点的优先级下降的时候,从上至下恢复堆的顺序
  2. up:在当某个节点的优先级上升的时候,从下至上恢复堆的顺序
  • down

    父节点与左右子节点比较,与最小的进行交换,如果最小的就是父节点本身则返回,否则交换后的父节点(当前的子节点)再作为父节点重新down

    // 需要down(下沉)的元素在切片中的索引为i,n为heap的长度,将该元素下沉到该元素对应的子树合适的位置,从而满足该子树为最小堆的要求
    func down(nodes []Node, i, n int) {
    	parent := i
    	for leftSon, rightSon := 2*parent+1, 2*parent+2; leftSon < n || rightSon < n; leftSon, rightSon = 2*parent+1, 2*parent+2 {
    		next := parent
    		if leftSon < n && nodes[parent].Value > nodes[leftSon].Value {
    			next = leftSon
    		}
    		if rightSon < n && nodes[parent].Value > nodes[rightSon].Value {
    			if nodes[rightSon].Value < nodes[next].Value {
    				next = rightSon
    			}
    		}
    		if next == parent {
    			break
    		}
    		nodes[parent].Value, nodes[next].Value = nodes[next].Value, nodes[parent].Value
    		parent = next
    	}
    }
    
  • up

    子节点与父节点比较,如果子结点小的话,则需要进行相互交换,直到循环到下标到达结尾,反之不用交换,直接返回

    func up(nodes []Node, j int) {
    	son := j
    	for parent := (son - 1) / 2; parent >= 0; {
    		if nodes[parent].Value <= nodes[son].Value {
    			break
    		} else {
    			nodes[parent].Value, nodes[son].Value = nodes[son].Value, nodes[parent].Value
    			son = parent
    			parent = (son - 1) / 2
    		}
    	}
    }
    
  • Push,用到了上述的Up函数
    利用Go语言维护并测试最小堆_第1张图片

  • Pop,用到了上述的Down函数
    利用Go语言维护并测试最小堆_第2张图片

测试(gocheck)

Golang官方的testing package是不支持assert的。Gocheck在testing库之上,丰富了很多功能,带我们脱离Golang官方测试框架下无尽的“if…else…"苦海

gocheck官网

实用特性:

  1. assert断言 + 丰富的判断动词: deep multi-type 对比, 字符串比较(正则匹配)
  2. 按suite组织测试用例,支持suite级别的setup()和teardown()
  3. 创建、删除临时文件/目录

使用方法

  1. 安装包

    go get -u gopkg.in/check.v1
    
  2. 基本用法(引用官方文档)

    package hello_test
    
    import (
        "testing"
        "io"
    
        . "gopkg.in/check.v1"
    )
    
    // Hook up gocheck into the "go test" runner.
    func Test(t *testing.T) { TestingT(t) }
    
    //先声明该结构并创建将运行测试的函数
    type MySuite struct{}
    
    //套件将给定值注册为要运行的测试套件。给定值中以Test前缀开头的任何方法都将被视为测试方法。
    var _ = Suite(&MySuite{})
    
    func (s *MySuite) TestHelloWorld(c *C) {
        c.Assert(42, Equals, "42")
        c.Assert(io.ErrClosedPipe, ErrorMatches, "io: .*on closed pipe")
        c.Check(42, Equals, 42)
    }
    

完整代码

Github

你可能感兴趣的:(利用Go语言维护并测试最小堆)