golang实现的简单优先队列
下面是golang实现的简单优先队列,参考信息可以查看https://golang.org/pkg/container/heap/或者https://golang.google.cn/pkg/container/heap/,后面这个网址也是官方提供的网址,关于这个网页的说明,可以参考https://blog.golang.org/hello-china。
package queue import "container/heap" // QItem 表示存储到这个队列中需要实现的接口
type QItem interface {
Less(item QItem) bool
} // priorityQueueImpl 用于优先队列底层实现
type priorityQueueImpl []QItem // Len 获取队列长度
func (pqi priorityQueueImpl) Len() int {
return len(pqi)
} // Less 用来进行元素比较
func (pqi priorityQueueImpl) Less(i, j int) bool {
return pqi[i].Less(pqi[j])
} // Swap 进行交换
func (pqi priorityQueueImpl) Swap(i, j int) {
pqi[i], pqi[j] = pqi[j], pqi[i]
} // Push 用来将一个对象压入队列中
func (pqi *priorityQueueImpl) Push(x interface{}) {
item := x.(QItem)
*pqi = append(*pqi, item)
} // Pop 将一个对象弹出队列
func (pqi *priorityQueueImpl) Pop() interface{} {
old := *pqi
n := len(old)
item := old[n-1]
*pqi = old[0 : n-1]
return item
} // PriorityQueue 实现优先队列
type PriorityQueue struct {
priorityQueueImpl
} // NewPriorityQueue 用来构建PriorityQueue
func NewPriorityQueue() *PriorityQueue {
var pq PriorityQueue
heap.Init(&pq.priorityQueueImpl)
return &pq
} // Push 用来将一个对象压入到队列中
func (pq *PriorityQueue) Push(item QItem) {
heap.Push(&pq.priorityQueueImpl, item)
} // Pop 用来从队列中弹出一个对象
func (pq *PriorityQueue) Pop() QItem {
return heap.Pop(&pq.priorityQueueImpl).(QItem)
} // Front 用来获取当前队列中的最小值
func (pq *PriorityQueue) Front() QItem {
// 队列中第一位应该就是最小值
return pq.priorityQueueImpl[0]
} // Length 用来获取当前队列的长度
func (pq *PriorityQueue) Length() int {
return pq.priorityQueueImpl.Len()
}
如果希望一个结构可以存储到PriorityQueue中,需要实现QItem接口中的函数,即Less函数。下面给出一个简单的示例:
type Int int
func (i Int) Less(j QItem) bool {
return i < j.(Int)
}
注意func (i Int) Less(j QItem) bool中的传参是QItem,而不是Int,golang当前还不支持泛型,所以,如果想要实现C++的STL的那种效果,应该是不可能的,就算使用反射来使得更多的类型得到支持,也势必会带来很大的性能开销,这个是我不太乐见的。关于将Int类型作为参数进行使用,可以参考下面的测试代码,这个测试代码不太规范,不过测试效果应该可以实现:
func Test_NewPriorityQueue(t *testing.T) {
pq := NewPriorityQueue()
pq.Push(Int(5))
pq.Push(Int(8))
pq.Push(Int(3))
first := pq.Front()
if first != Int(3) {
t.Error("first should be 3")
return
}
first = pq.Pop()
if first != Int(3) {
t.Error("first should be 3")
return
}
second := pq.Pop()
if second != Int(5) {
t.Error("second should be 5")
return
}
pq.Push(Int(1))
length := pq.Length()
if length != 2 {
t.Error("length should be 2")
return
}
third := pq.Front()
if third != Int(1) {
t.Error("third should be 1")
return
}
third = pq.Pop()
if third != Int(1) {
t.Error("third should be 1")
return
}
fourth := pq.Pop()
if fourth != Int(8) {
t.Error("fourth should be 8")
return
}
length = pq.Length()
if length != 0 {
t.Error("empty length should be 0")
return
}
}
在实际使用中,可能需要对func (pq *PriorityQueue) Pop() QItem函数和func (pq *PriorityQueue) Front() QItem函数获得的值进行类型强转,使用起来更像是面向对象程序设计的那种方式了。对于需要动态修改优先队列中成员值的情况,可以参考实现。
golang实现的简单优先队列的更多相关文章
- 数据结构和算法(Golang实现)(1)简单入门Golang-前言
数据结构和算法在计算机科学里,有非常重要的地位.此系列文章尝试使用 Golang 编程语言来实现各种数据结构和算法,并且适当进行算法分析. 我们会先简单学习一下Golang,然后进入计算机程序世界的第 ...
- 数据结构和算法(Golang实现)(2)简单入门Golang-包、变量和函数
包.变量和函数 一.举个例子 现在我们来建立一个完整的程序main.go: // Golang程序入口的包名必须为 main package main // import "golang&q ...
- 数据结构和算法(Golang实现)(3)简单入门Golang-流程控制语句
流程控制语句 计算机编程语言中,流程控制语句很重要,可以让机器知道什么时候做什么事,做几次.主要有条件和循环语句. Golang只有一种循环:for,只有一种判断:if,还有一种特殊的switch条件 ...
- 数据结构和算法(Golang实现)(4)简单入门Golang-结构体和方法
结构体和方法 一.值,指针和引用 我们现在有一段程序: package main import "fmt" func main() { // a,b 是一个值 a := 5 b : ...
- 数据结构和算法(Golang实现)(5)简单入门Golang-接口
接口 在Golang世界中,有一种叫interface的东西,很是神奇. 一.数据类型 interface{} 如果你事前并不知道变量是哪种数据类型,不知道它是整数还是字符串,但是你还是想要使用它. ...
- 数据结构和算法(Golang实现)(6)简单入门Golang-并发、协程和信道
并发.协程和信道 Golang语言提供了go关键字,以及名为chan的数据类型,以及一些标准库的并发锁等,我们将会简单介绍一下并发的一些概念,然后学习这些Golang特征知识. 一.并发介绍 我们写程 ...
- 数据结构和算法(Golang实现)(7)简单入门Golang-标准库
使用标准库 一.避免重复造轮子 官方提供了很多库给我们用,是封装好的轮子,比如包fmt,我们多次使用它来打印数据. 我们可以查看到其里面的实现: package fmt func Println(a ...
- TODO:Golang UDP连接简单测试慎用Deadline
TODO:Golang UDP连接简单测试慎用Deadline UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interco ...
- Golang+chromedp+goquery 简单爬取动态数据
目录 Golang+chromedp+goquery 简单爬取动态数据 Golang的安装 下载golang软件 解压golang 配置golang 重新导入配置 chromedp框架的使用 实际的代 ...
随机推荐
- bootstrap-edittable 使用笔记之 (select, data,text, number)
可编辑列表的数据格式可以指定,常用的有select, data, text, number.代码如下. 前端代码: <table id="tb_product" class= ...
- TP5 model层 返回的对象转数组
打开 database.php 增加或修改参数'resultset_type' => '\think\Collection',即可连贯操作 model('user')->select()- ...
- Charles抓包遇到的问题
1.手机设置了代理但是连不上网,无法下载HTTPS证书,关闭电脑防火墙! 2.content乱码解决方案参考https://www.cnblogs.com/puresoul/p/7365761.htm ...
- 【转载】 第四范式涂威威:AutoML技术现状与未来展望
原文地址: https://www.jiqizhixin.com/articles/2018-07-12-17 -------------------------------------------- ...
- ckeditor_学习(2) 功能概览
这篇文章用来说明 ckeditor 的所有可配置的功能,分为终端用户配置和开发者配置 1.终端用户配置 用户接口 – 设置编辑器的UI和语言 Editor 尺寸设置 – 设置编辑器的尺寸 插入内容 – ...
- js数组操作-最佳图解
js数组操作-最佳图解
- git pull时报错:refusing to merge unrelated histories
在Github新建一个仓库,写了README文件,然后把本地一个写了仓库上传,首先pull,因为两个仓库不同,发现refusing to merge unrelated histories,无法pul ...
- Python学习之路基础篇--11-12Python基础,函数的装饰器
对于装饰器来说,就是在不改变函数的调用的情况下,对函数的前后增加了些许功能,这完全符合函数的 开放封闭 原则.装饰器的本质 其实就是一个闭包函数. 这是一个装饰器的步骤图 ret = func(*ar ...
- Python学习之路基础篇--07Python基础+编码、集合 和 深浅Copy
1 小数据池(节省内存) 只有数字和字符串中内存,储存在同一个内存地址中 数字的范围在-5~256中,字符串有以下两个特点:不能含有特殊字符,还有就s*20 不是同一个地址,而要*21就不是了 2 编 ...
- HBase应用快速开发
有人说过“让Hadoop开发像家庭作业一样简单”,容器技术的出现让这成为可能,可以用Docker封装HBase运行环境,通过统一的接口来运行.本文将介绍如何在十分钟内跑起你的HBase应用. 首先,我 ...