From 3546afe86c4affed890c10ebbc9a6842f764d23d Mon Sep 17 00:00:00 2001 From: dudaodong Date: Wed, 2 Feb 2022 22:41:49 +0800 Subject: [PATCH] feat: add some functons of singlelink --- datastructure/linknode.go | 13 ++++ datastructure/singlylink.go | 105 ++++++++++++++++++++++++++++--- datastructure/singlylink_test.go | 62 ++++++++++++++++++ 3 files changed, 173 insertions(+), 7 deletions(-) create mode 100644 datastructure/linknode.go create mode 100644 datastructure/singlylink_test.go diff --git a/datastructure/linknode.go b/datastructure/linknode.go new file mode 100644 index 0000000..bf89e31 --- /dev/null +++ b/datastructure/linknode.go @@ -0,0 +1,13 @@ +package datastructure + +// LinkNode is a linkedlist node, which have a value and Pre points to previous node, Next points to a next node of the link. +type LinkNode[T any] struct { + Value T + Pre *LinkNode[T] + Next *LinkNode[T] +} + +func NewLinkNode[T any](value T) *LinkNode[T] { + return &LinkNode[T]{value, nil, nil} +} + diff --git a/datastructure/singlylink.go b/datastructure/singlylink.go index c06cc79..ed758e8 100644 --- a/datastructure/singlylink.go +++ b/datastructure/singlylink.go @@ -1,12 +1,103 @@ package datastructure -// Node is a linkedlist node, which have a value and Pre points to previous node, Next points to a next node of the link. -type Node[T any] struct { - Value T - Pre *Node[T] - Next *Node[T] +import ( + "errors" + "fmt" +) + +// SinglyLink is a linkedlist of node, which have a value and Pre points to previous node, Next points to a next node of the link. +type SinglyLink[T any] struct { + Head *LinkNode[T] + length int } -func NewNode[T any](value T) *Node[T] { - return &Node[T]{value, nil, nil} +// NewSinglyLink return *SinglyLink instance +func NewSinglyLink[T any]() *SinglyLink[T] { + return &SinglyLink[T]{Head: nil} +} + +// Values return slice of all singly linklist node value +func (link *SinglyLink[T]) Values() []T { + res := []T{} + current := link.Head + for current != nil { + res = append(res, current.Value) + current = current.Next + } + return res +} + +// Print all nodes info of a linked list +func (link *SinglyLink[T]) Print() { + current := link.Head + info := "[ " + for current != nil { + info += fmt.Sprintf("%+v, ", current) + current = current.Next + } + info += " ]" + fmt.Println(info) +} + +// InsertAtHead insert value into singly linklist at head index +func (link *SinglyLink[T]) InsertAtHead(value T) { + newNode := NewLinkNode(value) + newNode.Next = link.Head + link.Head = newNode + link.length++ +} + +// InsertAtTail insert value into singly linklist at tail index +func (link *SinglyLink[T]) InsertAtTail(value T) { + current := link.Head + if current == nil { + link.InsertAtHead(value) + return + } + + for current.Next != nil { + current = current.Next + } + + newNode := NewLinkNode(value) + newNode.Next = nil + current.Next = newNode + + link.length++ +} + +// InsertAt insert value into singly linklist at index +func (link *SinglyLink[T]) InsertAt(index int, value T) error { + size := link.length + if index < 0 || index > size { + return errors.New("param index should between 0 and the length of singly link.") + } + + if index == 0 { + link.InsertAtHead(value) + return nil + } + + if index == size { + link.InsertAtTail(value) + return nil + } + + i := 0 + current := link.Head + + for current != nil { + if i == index-1 { + newNode := NewLinkNode(value) + newNode.Next = current.Next + current.Next = newNode + link.length++ + + return nil + } + i++ + current = current.Next + } + + return errors.New("singly link no exist") } diff --git a/datastructure/singlylink_test.go b/datastructure/singlylink_test.go new file mode 100644 index 0000000..4322594 --- /dev/null +++ b/datastructure/singlylink_test.go @@ -0,0 +1,62 @@ +package datastructure + +import ( + "testing" + + "github.com/duke-git/lancet/internal" +) + +func TestSinglyLink_InsertAtFirst(t *testing.T) { + assert := internal.NewAssert(t, "TestSinglyLink_InsertAtFirst") + + link := NewSinglyLink[int]() + link.InsertAtHead(1) + link.InsertAtHead(2) + link.InsertAtHead(3) + link.Print() + + expected := []int{3, 2, 1} + values := link.Values() + + assert.Equal(expected, values) +} + +func TestSinglyLink_InsertAtTail(t *testing.T) { + assert := internal.NewAssert(t, "TestSinglyLink_InsertAtTail") + + link := NewSinglyLink[int]() + link.InsertAtTail(1) + link.InsertAtTail(2) + link.InsertAtTail(3) + link.Print() + + expected := []int{1, 2, 3} + values := link.Values() + + assert.Equal(expected, values) +} + +func TestSinglyLink_InsertAt(t *testing.T) { + assert := internal.NewAssert(t, "TestSinglyLink_InsertAt") + + link := NewSinglyLink[int]() + + err := link.InsertAt(1, 1) + assert.IsNotNil(err) + + err = link.InsertAt(0, 1) + err = link.InsertAt(1, 2) + err = link.InsertAt(2, 4) + err = link.InsertAt(2, 3) + + if err != nil { + t.FailNow() + } + link.Print() + + expected := []int{1, 2, 3, 4} + values := link.Values() + + assert.Equal(expected, values) + +}