Skip to content

Instantly share code, notes, and snippets.

@kiinoda
Last active November 2, 2023 14:03
Show Gist options
  • Save kiinoda/29e7ba2cd5f477f4409bac8392a5740f to your computer and use it in GitHub Desktop.
Save kiinoda/29e7ba2cd5f477f4409bac8392a5740f to your computer and use it in GitHub Desktop.
Linked List in Go, w/ Generics
package main
import (
"bytes"
"fmt"
"io"
"os"
)
type Node[T comparable] struct {
value T
next *Node[T]
}
type List[T comparable] struct {
head *Node[T]
tail *Node[T]
}
func NewList[T comparable]() *List[T] {
return &List[T]{
head: nil,
tail: nil,
}
}
func (l *List[T]) Append(value T) {
nn := Node[T]{
value: value,
next: nil,
}
if l.head == nil {
l.head = &nn
l.tail = &nn
return
}
if l.head == l.tail {
l.head.next = &nn
l.tail = &nn
return
}
l.tail.next = &nn
l.tail = &nn
return
}
func (l *List[T]) Prepend(value T) {
nn := Node[T]{
value: value,
next: nil,
}
if l.head == nil {
l.head = &nn
l.tail = &nn
return
}
nn.next = l.head
l.head = &nn
}
func (l *List[T]) AddBefore(valueToSearch, valueToAdd T) {
back := l.head
for curr := l.head; curr != nil; curr = curr.next {
if curr.value == valueToSearch {
if curr == l.head {
l.Prepend(valueToAdd)
return
} else {
nn := Node[T]{
value: valueToAdd,
next: curr,
}
back.next = &nn
return
}
}
back = curr
}
}
func (l *List[T]) AddAfter(valueToSearch, valueToAdd T) {
for curr := l.head; curr != nil; curr = curr.next {
if curr.value == valueToSearch {
if curr == l.tail {
l.Append(valueToAdd)
return
} else {
nn := Node[T]{
value: valueToAdd,
next: curr.next,
}
curr.next = &nn
return
}
}
}
}
func (l *List[T]) Output() string {
var buffer bytes.Buffer
for curr := l.head; curr != nil; curr = curr.next {
buffer.WriteString(fmt.Sprint(curr.value, ", "))
}
return buffer.String()
}
func (l *List[T]) ReversedOutput() string {
var buffer bytes.Buffer
var reverseIntoBuffer func(curr *Node[T])
reverseIntoBuffer = func(curr *Node[T]) {
if curr.next != nil {
reverseIntoBuffer(curr.next)
}
buffer.WriteString(fmt.Sprint(curr.value, ", "))
}
reverseIntoBuffer(l.head)
return buffer.String()
}
func run(w io.Writer) {
const messageFormat = "%-25s: %s\n"
li := NewList[int]()
li.Append(7)
li.Append(5)
li.Append(1)
fmt.Fprintf(w, messageFormat, "Initial List (of ints)", li.Output())
li.Prepend(9)
fmt.Fprintf(w, messageFormat, "Prepended 9", li.Output())
li.AddBefore(9, 10)
li.AddBefore(5, 6)
li.AddBefore(1, 2)
fmt.Fprintf(w, messageFormat, "Added before for 3 times", li.Output())
li.AddAfter(10, 11)
li.AddAfter(5, 4)
li.AddAfter(11, 0)
fmt.Fprintf(w, messageFormat, "Added after for 3 times", li.Output())
fmt.Fprintf(w, messageFormat, "Printing list in reverse", li.ReversedOutput())
fmt.Println("---")
ls := NewList[string]()
ls.Append("7")
ls.Append("5")
ls.Append("1")
fmt.Fprintf(w, messageFormat, "Initial List (of strings)", ls.Output())
ls.Prepend("9")
fmt.Fprintf(w, messageFormat, "Prepended 9", ls.Output())
ls.AddBefore("9", "10")
ls.AddBefore("5", "6")
ls.AddBefore("1", "2")
fmt.Fprintf(w, messageFormat, "Added before for 3 times", ls.Output())
ls.AddAfter("10", "11")
ls.AddAfter("5", "4")
ls.AddAfter("11", "0")
fmt.Fprintf(w, messageFormat, "Added after for 3 times", ls.Output())
fmt.Fprintf(w, messageFormat, "Printing list in reverse", ls.ReversedOutput())
}
func main() {
run(os.Stdout)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment