list

package module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 15, 2024 License: MIT Imports: 1 Imported by: 0

README

Linked List Implementation in Go

Go Report Card Coverage

This repository contains:

  • a generic-based, thread-safe implementation of a doubly linked list with iterators support.
  • a generic-based implementation of intrusive singly linked list.

It was created to address the lack of iterators, async and generic support in Go's default container/list package.

Features

This linked list implementation provides the following features:

  • Generics: The linked list can store elements of any type, thanks to Go's support for generics.
  • Iterators: The Begin and End methods allow you to iterate over the list from the head to the tail and vice versa, respectively.
  • Node Access: The Head, Tail, Next, and Prev methods provide access to the nodes of the list.
  • Node Manipulation: The PushBack, PushFront, PopBack, and PopFront methods allow you to add and remove nodes from the list.
  • List Information: The Size and Empty methods provide information about the list.
  • Intrusive List Support: The implementation allows you to embed the linked list structure directly within your own structs, enabling efficient memory usage and manipulation without the need for separate node types.

Table of Contents

Doubly Linked List

Doubly linked list is created with:

  • NewSyncLinked[T](): Creates a new synced linked list (all operations are blocking).
  • list.Linked[T]{}: Creates a new unsynced linked list

Here is a list of available methods with their descriptions:

  • PushBack(val T): Adds a new node with the given value at the end of the list.
  • PushFront(val T): Adds a new node with the given value at the beginning of the list.
  • PopBack() (T, bool): Removes the last node from the list and returns its value and a boolean indicating success.
  • PopFront() (T, bool): Removes the first node and returns its value and a boolean indicating success.
  • Head() *Node[T]: Returns the first node of the list.
  • Tail() *Node[T]: Returns the last node of the list.
  • Size() int: Returns the number of nodes in the list.
  • Empty() bool: Checks if the list is empty.
  • Begin(yield func(T) bool): Iterates over the list from the head to the tail.
  • End(yield func(T) bool): Iterates over the list from the tail to the head.
  • Val() T: Returns the value of the node.
  • Next() *Node[T]: Returns the next node.
  • Prev() *Node[T]: Returns the previous node.

Intrusive Singly Linked List

Intrusive Singly Linked List is created with:

type S struct { // suppose this is your struct
    a, b int // define your struct innies
    *list.List[S] // embed the List structure inside your package
}

Here is a list of available methods with their descriptions:

-- Next() *T: returns a pointer to the next element in the linked list. -- SetNext(next *T): assigns the 'next' pointer to the provided element, effectively making 'next' the subsequent element in the list. -- InsertNext(elem *T): InsertNext() inserts the provided element 'elem' as the subsequent element in the list. The element that was previously next becomes the next element of 'elem'. -- RemoveNext(): detaches the next element from the list. The element following the next element (if it exists) becomes the new next element.

Usage Example

Here is a simple usage example: try here

import (
	"fmt"
	"github.com/koss-null/list"
)

func foo() {
	// Create a new linked list
	ll := list.Linked[int]{}

	// Add elements to the list
	ll.PushBack(1)
	ll.PushBack(2)
	ll.PushBack(3)
	// The list contains: 1, 2, 3

	// Print the elements of the list
	for val := range ll.Begin {
		fmt.Println(val)
	}

	// Remove an element from the list
	val, ok := ll.PopBack()
	if ok {
		fmt.Printf("Popped value: %d\n", val)
		// Prints: Popped value: 3
	}

	// Print the size of the list
	fmt.Printf("List size: %d\n", ll.Size())
	// Prints: 2
}

Intrusive List Usage Example

This library also supports intrusive singly linked lists if you want to imbed it in your own structure. Here is the example:

import (
	"fmt"
	"github.com/koss-null/list"
)

type S struct {
	a, b int
	*list.List[S]
}

func NewS(a, b int) &S {
    return &S{a: a, b: b, List: &list.List[S]{}}
}

func foo() {
	// Create a new linked list
	head := NewS(1, 2)
	cur := head

	// Add elements to the list
	cur.SetNext(NewS(3, 4))
	cur = cur.Next()
	cur.SetNext(NewS(5, 6))

	// Print the elements of the list
	for node := head; node != nil; node = node.Next() {
		fmt.Println(node.a, node.b)
	}
	// 1 2 3 4 5 6

	// Remove an element from the list
	head.RemoveNext()

	// Print the elements of the list after removal
	for node := head; node != nil; node = node.Next() {
		fmt.Println(node.a, node.b)
	}
	// 1 2 5 6
}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Linked

type Linked[T any] struct {
	// contains filtered or unexported fields
}

Linked struct represents linked list

func NewSyncLinked

func NewSyncLinked[T any]() Linked[T]

NewSyncLinked creates a new instance of a synchronized linked list

func (*Linked[T]) Begin

func (list *Linked[T]) Begin(yield func(T) bool)

Begin iterates over the list from the head to the tail

func (*Linked[T]) Empty

func (list *Linked[T]) Empty() bool

Empty checks if the list is empty

func (*Linked[T]) End

func (list *Linked[T]) End(yield func(T) bool)

End iterates over the list from the tail to the head

func (*Linked[T]) Head

func (list *Linked[T]) Head() *Node[T]

Head returns the first node of the list

func (*Linked[T]) PopBack

func (list *Linked[T]) PopBack() (T, bool)

PopBack removes the last node from the list and returns its value and a boolean indicating success

func (*Linked[T]) PopFront

func (list *Linked[T]) PopFront() (T, bool)

PopFront removes the first node and returns its value and boolean indicating success

func (*Linked[T]) PushBack

func (list *Linked[T]) PushBack(val T)

PushBack adds a new node with the given value at the end of the list

func (*Linked[T]) PushFront

func (list *Linked[T]) PushFront(val T)

PushFront adds a new node with the given value at the beginning of the list

func (*Linked[T]) Size

func (list *Linked[T]) Size() int

Size returns the number of nodes in the list

func (*Linked[T]) Tail

func (list *Linked[T]) Tail() *Node[T]

Tail returns the last node of the list

type List added in v0.0.2

type List[T nexter[T]] struct {
	// contains filtered or unexported fields
}

List[T nexter[T]] is a type parameterized struct. It should be embedded in other structs to provide them with the ability to be nodes in a singly linked list

func (*List[T]) InsertNext added in v0.0.2

func (l *List[T]) InsertNext(elem *T)

InsertNext() inserts the provided element 'elem' as the subsequent element in the list. The element that was previously next becomes the next element of 'elem'

func (*List[T]) Next added in v0.0.2

func (l *List[T]) Next() *T

Next() returns a pointer to the next element in the linked list

func (*List[T]) RemoveNext added in v0.0.2

func (l *List[T]) RemoveNext()

RemoveNext() detaches the next element from the list. The element following the next element (if it exists) becomes the new next element

func (*List[T]) SetNext added in v0.0.2

func (l *List[T]) SetNext(next *T)

SetNext() assigns the 'next' pointer to the provided element, effectively making 'next' the subsequent element in the list

type Node

type Node[T any] struct {
	// contains filtered or unexported fields
}

Node is a linked list object item

func (*Node[T]) Next

func (node *Node[T]) Next() *Node[T]

Next returns the next node

func (*Node[T]) Prev

func (node *Node[T]) Prev() *Node[T]

Prev returns the previous node

func (*Node[T]) Val

func (node *Node[T]) Val() T

Val returns the value of the node

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL