feat(queue): 自 go-hua/queue 原样迁入链式队列
- 代码与测试不变,附 examples/queue 例程与包 README(含哨兵头结点 Pop 语义说明)
This commit is contained in:
@@ -0,0 +1,29 @@
|
|||||||
|
// queue 包示例:链式队列(Create 批量建队、Push 入列、Pop 出队、Print、Length)
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.zeroonesoft.cn/golib/zogo/queue"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// 头结点作为哨兵,Create 批量创建队列元素
|
||||||
|
q := &queue.QueueNode{}
|
||||||
|
q.Create(1, 2, 3)
|
||||||
|
fmt.Print("Create 后队列: ")
|
||||||
|
q.Print()
|
||||||
|
fmt.Println("Length:", q.Length())
|
||||||
|
|
||||||
|
// Push 入列(追加到队尾)
|
||||||
|
q.Push(4)
|
||||||
|
fmt.Print("Push 4 后: ")
|
||||||
|
q.Print()
|
||||||
|
fmt.Println("Length:", q.Length())
|
||||||
|
|
||||||
|
// Pop 出队:在头结点上调用,返回头结点自身 Data(哨兵为 nil),并使队列前进一个节点
|
||||||
|
_ = q.Pop()
|
||||||
|
fmt.Print("Pop 后队列: ")
|
||||||
|
q.Print()
|
||||||
|
fmt.Println("Length:", q.Length())
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# queue
|
||||||
|
|
||||||
|
基于链表实现的先进先出队列(哨兵头结点风格)。
|
||||||
|
|
||||||
|
> 迁移自 go-hua/queue,代码保持原样。
|
||||||
|
|
||||||
|
## 用法
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "git.zeroonesoft.cn/golib/zogo/queue"
|
||||||
|
|
||||||
|
// 头结点作为哨兵,Create 批量建队
|
||||||
|
q := &queue.QueueNode{}
|
||||||
|
q.Create(1, 2, 3)
|
||||||
|
q.Length() // 3
|
||||||
|
|
||||||
|
// Push 入列(追加队尾)/ Pop 出队
|
||||||
|
q.Push(4)
|
||||||
|
v := q.Pop() // 在头结点上调用:返回头结点自身 Data(哨兵为 nil),队列前进一个节点
|
||||||
|
q.Print() // 打印剩余元素
|
||||||
|
```
|
||||||
|
|
||||||
|
完整可运行例程:[examples/queue/main.go](../examples/queue/main.go)
|
||||||
|
|
||||||
|
## 注意
|
||||||
|
|
||||||
|
- `Pop` 语义特殊:在**哨兵头结点**上调用,返回的是哨兵自身的 `Data`(通常为 nil)
|
||||||
|
并让队列前进一格;取真正的队头元素请在 `q.Next` 上调用或先取 `q.Next.Data`。
|
||||||
|
- `Pop` 在队列仅剩哨兵(`Next == nil`)时调用会 panic,出队前先判断 `Length()`。
|
||||||
|
- 元素为 `interface{}`,非泛型非并发安全,多 goroutine 场景需外加拉锁。
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
// Package queue 基于链表实现的先进先出队列。
|
||||||
|
package queue
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// QueueNode 队列节点,Data 存任意数据,Next 指向下一节点
|
||||||
|
type QueueNode struct {
|
||||||
|
Data interface{}
|
||||||
|
Next *QueueNode
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建链列(数据)
|
||||||
|
func (queue *QueueNode) Create(Data ...interface{}) {
|
||||||
|
if queue == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(Data) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//创建链列
|
||||||
|
for _, v := range Data {
|
||||||
|
newNode := new(QueueNode)
|
||||||
|
newNode.Data = v
|
||||||
|
|
||||||
|
queue.Next = newNode
|
||||||
|
queue = queue.Next
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打印链列
|
||||||
|
func (queue *QueueNode) Print() {
|
||||||
|
if queue == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for queue != nil {
|
||||||
|
if queue.Data != nil {
|
||||||
|
fmt.Print(queue.Data, " ")
|
||||||
|
}
|
||||||
|
queue = queue.Next
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 链列个数
|
||||||
|
func (queue *QueueNode) Length() int {
|
||||||
|
if queue == nil {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for queue.Next != nil {
|
||||||
|
i++
|
||||||
|
queue = queue.Next
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
// 入列(insert)
|
||||||
|
func (queue *QueueNode) Push(Data interface{}) {
|
||||||
|
//放在队列的末尾
|
||||||
|
|
||||||
|
if queue == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if Data == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//找到队列末尾
|
||||||
|
for queue.Next != nil {
|
||||||
|
queue = queue.Next
|
||||||
|
}
|
||||||
|
|
||||||
|
//创建新节点 将新节点加入队列末尾
|
||||||
|
newNode := new(QueueNode)
|
||||||
|
newNode.Data = Data
|
||||||
|
|
||||||
|
queue.Next = newNode
|
||||||
|
}
|
||||||
|
|
||||||
|
// 出队(delete)
|
||||||
|
func (queue *QueueNode) Pop() interface{} {
|
||||||
|
//队头出列
|
||||||
|
if queue == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
//记录列队第一个的节点
|
||||||
|
//node:=queue.Next
|
||||||
|
//queue.Next=node.Next
|
||||||
|
data := queue.Data
|
||||||
|
queue.Next = queue.Next.Next
|
||||||
|
return data
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package queue
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestCreateAndLength(t *testing.T) {
|
||||||
|
q := &QueueNode{}
|
||||||
|
q.Create(1, 2, 3)
|
||||||
|
if got := q.Length(); got != 3 {
|
||||||
|
t.Errorf("Length = %d, want 3", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPush(t *testing.T) {
|
||||||
|
q := &QueueNode{}
|
||||||
|
q.Create("a")
|
||||||
|
q.Push("b")
|
||||||
|
if got := q.Length(); got != 2 {
|
||||||
|
t.Errorf("Push 后 Length = %d, want 2", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPop(t *testing.T) {
|
||||||
|
q := &QueueNode{}
|
||||||
|
q.Create(1, 2, 3)
|
||||||
|
// Pop 在头结点(哨兵)上调用,跳过第一个元素并返回头结点 Data
|
||||||
|
q.Pop()
|
||||||
|
if got := q.Length(); got != 2 {
|
||||||
|
t.Errorf("Pop 后 Length = %d, want 2", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateEmpty(t *testing.T) {
|
||||||
|
q := &QueueNode{}
|
||||||
|
q.Create() // 无元素,不应 panic
|
||||||
|
if got := q.Length(); got != 0 {
|
||||||
|
t.Errorf("空 Create 后 Length = %d, want 0", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrint(t *testing.T) {
|
||||||
|
q := &QueueNode{}
|
||||||
|
q.Create(1, 2, 3)
|
||||||
|
q.Print() // 仅验证不 panic
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user