mirror of
https://github.com/duke-git/lancet.git
synced 2026-03-01 00:35:28 +08:00
feat: add LinkedQueue
This commit is contained in:
@@ -26,7 +26,7 @@ func NewStackNode[T any](value T) *StackNode[T] {
|
|||||||
// QueueNode is a node in a queue, which have a Value and Next pointer points to next node in the queue.
|
// QueueNode is a node in a queue, which have a Value and Next pointer points to next node in the queue.
|
||||||
type QueueNode[T any] struct {
|
type QueueNode[T any] struct {
|
||||||
Value T
|
Value T
|
||||||
Next *StackNode[T]
|
Next *QueueNode[T]
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewQueueNode return a QueueNode pointer
|
// NewQueueNode return a QueueNode pointer
|
||||||
|
|||||||
104
datastructure/queue/linkedqueue.go
Normal file
104
datastructure/queue/linkedqueue.go
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package datastructure
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/datastructure"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LinkedQueue implements queue with link list
|
||||||
|
type LinkedQueue[T any] struct {
|
||||||
|
head *datastructure.QueueNode[T]
|
||||||
|
tail *datastructure.QueueNode[T]
|
||||||
|
length int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLinkedQueue return a empty LinkedQueue pointer
|
||||||
|
func NewLinkedQueue[T any]() *LinkedQueue[T] {
|
||||||
|
return &LinkedQueue[T]{head: nil, tail: nil, length: 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data return queue data
|
||||||
|
func (q *LinkedQueue[T]) Data() []T {
|
||||||
|
res := []T{}
|
||||||
|
current := q.head
|
||||||
|
|
||||||
|
for current != nil {
|
||||||
|
res = append(res, current.Value)
|
||||||
|
current = current.Next
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size return length of queue data
|
||||||
|
func (q *LinkedQueue[T]) Size() int {
|
||||||
|
return q.length
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty checks if queue is empty or not
|
||||||
|
func (q *LinkedQueue[T]) IsEmpty() bool {
|
||||||
|
return q.length == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnQueue add element into queue
|
||||||
|
func (q *LinkedQueue[T]) EnQueue(value T) {
|
||||||
|
newNode := datastructure.NewQueueNode(value)
|
||||||
|
|
||||||
|
if q.IsEmpty() {
|
||||||
|
q.head = newNode
|
||||||
|
q.tail = newNode
|
||||||
|
} else {
|
||||||
|
q.tail.Next = newNode
|
||||||
|
q.tail = newNode
|
||||||
|
}
|
||||||
|
q.length++
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeQueue delete head element of queue then return it, if queue is empty, return nil and error
|
||||||
|
func (q *LinkedQueue[T]) DeQueue() (*T, error) {
|
||||||
|
if q.IsEmpty() {
|
||||||
|
return nil, errors.New("queue is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
head := q.head
|
||||||
|
q.head = q.head.Next
|
||||||
|
q.length--
|
||||||
|
|
||||||
|
return &head.Value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Front return front value of queue
|
||||||
|
func (q *LinkedQueue[T]) Front() (*T, error) {
|
||||||
|
if q.IsEmpty() {
|
||||||
|
return nil, errors.New("queue is empty")
|
||||||
|
}
|
||||||
|
return &q.head.Value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Back return back value of queue
|
||||||
|
func (q *LinkedQueue[T]) Back() (*T, error) {
|
||||||
|
if q.IsEmpty() {
|
||||||
|
return nil, errors.New("queue is empty")
|
||||||
|
}
|
||||||
|
return &q.tail.Value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear clear the queue data
|
||||||
|
func (q *LinkedQueue[T]) Clear() {
|
||||||
|
q.head = nil
|
||||||
|
q.tail = nil
|
||||||
|
q.length = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print all nodes info of queue link
|
||||||
|
func (s *LinkedQueue[T]) Print() {
|
||||||
|
current := s.head
|
||||||
|
info := "[ "
|
||||||
|
for current != nil {
|
||||||
|
info += fmt.Sprintf("%+v, ", current)
|
||||||
|
current = current.Next
|
||||||
|
}
|
||||||
|
info += " ]"
|
||||||
|
fmt.Println(info)
|
||||||
|
}
|
||||||
84
datastructure/queue/linkedqueue_test.go
Normal file
84
datastructure/queue/linkedqueue_test.go
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package datastructure
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/duke-git/lancet/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLinkedQueue_EnQueue(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestLinkedQueue_EnQueue")
|
||||||
|
|
||||||
|
queue := NewLinkedQueue[int]()
|
||||||
|
queue.EnQueue(1)
|
||||||
|
queue.EnQueue(2)
|
||||||
|
queue.EnQueue(3)
|
||||||
|
|
||||||
|
queue.Print()
|
||||||
|
|
||||||
|
assert.Equal([]int{1, 2, 3}, queue.Data())
|
||||||
|
assert.Equal(3, queue.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLinkedQueue_DeQueue(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestLinkedQueue_DeQueue")
|
||||||
|
|
||||||
|
queue := NewLinkedQueue[int]()
|
||||||
|
queue.EnQueue(1)
|
||||||
|
queue.EnQueue(2)
|
||||||
|
queue.EnQueue(3)
|
||||||
|
|
||||||
|
val, _ := queue.DeQueue()
|
||||||
|
|
||||||
|
queue.Print()
|
||||||
|
|
||||||
|
assert.Equal([]int{2, 3}, queue.Data())
|
||||||
|
assert.Equal(1, *val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLinkedQueue_Front(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestLinkedQueue_Front")
|
||||||
|
|
||||||
|
queue := NewLinkedQueue[int]()
|
||||||
|
val, err := queue.Front()
|
||||||
|
assert.IsNotNil(err)
|
||||||
|
|
||||||
|
queue.EnQueue(1)
|
||||||
|
queue.EnQueue(2)
|
||||||
|
queue.EnQueue(3)
|
||||||
|
|
||||||
|
val, err = queue.Front()
|
||||||
|
assert.Equal(1, *val)
|
||||||
|
assert.IsNil(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLinkedQueue_Back(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
|
||||||
|
|
||||||
|
queue := NewLinkedQueue[int]()
|
||||||
|
val, err := queue.Back()
|
||||||
|
assert.IsNotNil(err)
|
||||||
|
|
||||||
|
queue.EnQueue(1)
|
||||||
|
queue.EnQueue(2)
|
||||||
|
queue.EnQueue(3)
|
||||||
|
|
||||||
|
val, err = queue.Back()
|
||||||
|
assert.Equal(3, *val)
|
||||||
|
assert.IsNil(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLinkedQueue_Clear(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestLinkedQueue_Back")
|
||||||
|
|
||||||
|
queue := NewLinkedQueue[int]()
|
||||||
|
assert.Equal(true, queue.IsEmpty())
|
||||||
|
|
||||||
|
queue.EnQueue(1)
|
||||||
|
queue.EnQueue(2)
|
||||||
|
queue.EnQueue(3)
|
||||||
|
assert.Equal(false, queue.IsEmpty())
|
||||||
|
|
||||||
|
queue.Clear()
|
||||||
|
assert.Equal(true, queue.IsEmpty())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user