mirror of
https://github.com/duke-git/lancet.git
synced 2025-09-26 19:41:20 +08:00
243 lines
4.5 KiB
Go
243 lines
4.5 KiB
Go
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
|
// Use of this source code is governed by MIT license
|
|
|
|
// Package datastructure contains some data structure. Link structure contains SinglyLink and DoublyLink.
|
|
package datastructure
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/duke-git/lancet/v2/datastructure"
|
|
)
|
|
|
|
// DoublyLink is a linked list. Whose node has a generic Value, Pre pointer points to a previous node of the dl, Next pointer points to a next node of the dl.
|
|
type DoublyLink[T any] struct {
|
|
Head *datastructure.LinkNode[T]
|
|
length int
|
|
}
|
|
|
|
// NewDoublyLink return *DoublyLink instance
|
|
func NewDoublyLink[T any]() *DoublyLink[T] {
|
|
return &DoublyLink[T]{Head: nil}
|
|
}
|
|
|
|
// InsertAtHead insert value into doubly linklist at head index
|
|
func (dl *DoublyLink[T]) InsertAtHead(value T) {
|
|
newNode := datastructure.NewLinkNode(value)
|
|
size := dl.Size()
|
|
|
|
if size == 0 {
|
|
dl.Head = newNode
|
|
dl.length++
|
|
return
|
|
}
|
|
|
|
newNode.Next = dl.Head
|
|
newNode.Pre = nil
|
|
|
|
dl.Head.Pre = newNode
|
|
dl.Head = newNode
|
|
|
|
dl.length++
|
|
}
|
|
|
|
// InsertAtTail insert value into doubly linklist at tail index
|
|
func (dl *DoublyLink[T]) InsertAtTail(value T) {
|
|
current := dl.Head
|
|
if current == nil {
|
|
dl.InsertAtHead(value)
|
|
return
|
|
}
|
|
|
|
for current.Next != nil {
|
|
current = current.Next
|
|
}
|
|
|
|
newNode := datastructure.NewLinkNode(value)
|
|
newNode.Next = nil
|
|
newNode.Pre = current
|
|
current.Next = newNode
|
|
|
|
dl.length++
|
|
}
|
|
|
|
// InsertAt insert value into doubly linklist at index
|
|
// param `index` should between [0, length], if index do not meet the conditions, do nothing
|
|
func (dl *DoublyLink[T]) InsertAt(index int, value T) {
|
|
size := dl.length
|
|
if index < 0 || index > size {
|
|
return
|
|
}
|
|
|
|
if index == 0 {
|
|
dl.InsertAtHead(value)
|
|
return
|
|
}
|
|
|
|
if index == size {
|
|
dl.InsertAtTail(value)
|
|
return
|
|
}
|
|
|
|
i := 0
|
|
current := dl.Head
|
|
|
|
for current != nil {
|
|
if i == index-1 {
|
|
newNode := datastructure.NewLinkNode(value)
|
|
newNode.Next = current.Next
|
|
newNode.Pre = current
|
|
|
|
current.Next = newNode
|
|
dl.length++
|
|
|
|
return
|
|
}
|
|
i++
|
|
current = current.Next
|
|
}
|
|
}
|
|
|
|
// DeleteAtHead delete value in doubly linklist at head index
|
|
func (dl *DoublyLink[T]) DeleteAtHead() {
|
|
if dl.Head == nil {
|
|
return
|
|
}
|
|
|
|
current := dl.Head
|
|
dl.Head = current.Next
|
|
dl.Head.Pre = nil
|
|
dl.length--
|
|
}
|
|
|
|
// DeleteAtTail delete value in doubly linklist at tail
|
|
func (dl *DoublyLink[T]) DeleteAtTail() {
|
|
if dl.Head == nil {
|
|
return
|
|
}
|
|
|
|
current := dl.Head
|
|
if current.Next == nil {
|
|
dl.DeleteAtHead()
|
|
}
|
|
|
|
for current.Next.Next != nil {
|
|
current = current.Next
|
|
}
|
|
|
|
current.Next = nil
|
|
dl.length--
|
|
}
|
|
|
|
// DeleteAt delete value in doubly linklist at index
|
|
// param `index` should be [0, len(DoublyLink)-1]
|
|
func (dl *DoublyLink[T]) DeleteAt(index int) {
|
|
if dl.Head == nil {
|
|
return
|
|
}
|
|
|
|
current := dl.Head
|
|
if current.Next == nil || index == 0 {
|
|
dl.DeleteAtHead()
|
|
}
|
|
|
|
if index == dl.length-1 {
|
|
dl.DeleteAtTail()
|
|
}
|
|
|
|
if index < 0 || index > dl.length-1 {
|
|
return
|
|
}
|
|
|
|
i := 0
|
|
for current != nil {
|
|
if i == index-1 {
|
|
current.Next = current.Next.Next
|
|
dl.length--
|
|
return
|
|
}
|
|
i++
|
|
current = current.Next
|
|
}
|
|
}
|
|
|
|
// Reverse the linked list
|
|
func (dl *DoublyLink[T]) Reverse() {
|
|
current := dl.Head
|
|
var temp *datastructure.LinkNode[T]
|
|
|
|
for current != nil {
|
|
temp = current.Pre
|
|
current.Pre = current.Next
|
|
current.Next = temp
|
|
current = current.Pre
|
|
}
|
|
|
|
if temp != nil {
|
|
dl.Head = temp.Pre
|
|
}
|
|
}
|
|
|
|
// GetMiddleNode return node at middle index of linked list
|
|
func (dl *DoublyLink[T]) GetMiddleNode() *datastructure.LinkNode[T] {
|
|
if dl.Head == nil {
|
|
return nil
|
|
}
|
|
if dl.Head.Next == nil {
|
|
return dl.Head
|
|
}
|
|
fast := dl.Head
|
|
slow := dl.Head
|
|
|
|
for fast != nil {
|
|
fast = fast.Next
|
|
|
|
if fast != nil {
|
|
fast = fast.Next
|
|
slow = slow.Next
|
|
} else {
|
|
return slow
|
|
}
|
|
}
|
|
return slow
|
|
}
|
|
|
|
// Size return the count of doubly linked list
|
|
func (dl *DoublyLink[T]) Size() int {
|
|
return dl.length
|
|
}
|
|
|
|
// Values return slice of all doubly linklist node value
|
|
func (dl *DoublyLink[T]) Values() []T {
|
|
result := make([]T, 0, dl.length)
|
|
current := dl.Head
|
|
for current != nil {
|
|
result = append(result, current.Value)
|
|
current = current.Next
|
|
}
|
|
return result
|
|
}
|
|
|
|
// Print all nodes info of a linked list
|
|
func (dl *DoublyLink[T]) Print() {
|
|
current := dl.Head
|
|
info := "[ "
|
|
for current != nil {
|
|
info += fmt.Sprintf("%+v, ", current)
|
|
current = current.Next
|
|
}
|
|
info += " ]"
|
|
fmt.Println(info)
|
|
}
|
|
|
|
// IsEmpty checks if dl is empty or not
|
|
func (dl *DoublyLink[T]) IsEmpty() bool {
|
|
return dl.length == 0
|
|
}
|
|
|
|
// Clear all nodes in doubly linklist
|
|
func (dl *DoublyLink[T]) Clear() {
|
|
dl.Head = nil
|
|
dl.length = 0
|
|
}
|