By Golang

  1. // Package linkedlist creates a ItemLinkedList data structure for the Item type
  2. package linkedlist
  3. import (
  4. "fmt"
  5. "sync"
  6. )
  7. // Item the type of the linked list
  8. type Item interface{}
  9. // Node a single node that composes the list
  10. type Node struct {
  11. content Item
  12. next *Node
  13. }
  14. // ItemLinkedList the linked list of Items
  15. type ItemLinkedList struct {
  16. head *Node
  17. size int
  18. lock sync.RWMutex
  19. }
  20. // Append adds an Item to the end of the linked list
  21. func (ll *ItemLinkedList) Append(t Item) {
  22. ll.lock.Lock()
  23. node := Node{t, nil}
  24. if ll.head == nil {
  25. ll.head = &node
  26. } else {
  27. last := ll.head
  28. for {
  29. if last.next == nil {
  30. break
  31. }
  32. last = last.next
  33. }
  34. last.next = &node
  35. }
  36. ll.size++
  37. ll.lock.Unlock()
  38. }
  39. // Insert adds an Item at position i
  40. func (ll *ItemLinkedList) Insert(i int, t Item) error {
  41. ll.lock.Lock()
  42. defer ll.lock.Unlock()
  43. if i < 0 || i > ll.size {
  44. return fmt.Errorf("Index out of bounds")
  45. }
  46. addNode := Node{t, nil}
  47. if i == 0 {
  48. addNode.next = ll.head
  49. ll.head = &addNode
  50. return nil
  51. }
  52. node := ll.head
  53. j := 0
  54. for j < i-2 {
  55. j++
  56. node = node.next
  57. }
  58. addNode.next = node.next
  59. node.next = &addNode
  60. ll.size++
  61. return nil
  62. }
  63. // RemoveAt removes a node at position i
  64. func (ll *ItemLinkedList) RemoveAt(i int) (*Item, error) {
  65. ll.lock.Lock()
  66. defer ll.lock.Unlock()
  67. if i < 0 || i > ll.size {
  68. return nil, fmt.Errorf("Index out of bounds")
  69. }
  70. node := ll.head
  71. j := 0
  72. for j < i-1 {
  73. j++
  74. node = node.next
  75. }
  76. remove := node.next
  77. node.next = remove.next
  78. ll.size--
  79. return &remove.content, nil
  80. }
  81. // IndexOf returns the position of the Item t
  82. func (ll *ItemLinkedList) IndexOf(t Item) int {
  83. ll.lock.RLock()
  84. defer ll.lock.RUnlock()
  85. node := ll.head
  86. j := 0
  87. for {
  88. if node.content == t {
  89. return j
  90. }
  91. if node.next == nil {
  92. return -1
  93. }
  94. node = node.next
  95. j++
  96. }
  97. }
  98. // IsEmpty returns true if the list is empty
  99. func (ll *ItemLinkedList) IsEmpty() bool {
  100. ll.lock.RLock()
  101. defer ll.lock.RUnlock()
  102. if ll.head == nil {
  103. return true
  104. }
  105. return false
  106. }
  107. // Size returns the linked list size
  108. func (ll *ItemLinkedList) Size() int {
  109. ll.lock.RLock()
  110. defer ll.lock.RUnlock()
  111. size := 1
  112. last := ll.head
  113. for {
  114. if last == nil || last.next == nil {
  115. break
  116. }
  117. last = last.next
  118. size++
  119. }
  120. return size
  121. }
  122. // Insert adds an Item at position i
  123. func (ll *ItemLinkedList) String() {
  124. ll.lock.RLock()
  125. defer ll.lock.RUnlock()
  126. node := ll.head
  127. j := 0
  128. for {
  129. if node == nil {
  130. break
  131. }
  132. j++
  133. fmt.Print(node.content)
  134. fmt.Print(" ")
  135. node = node.next
  136. }
  137. fmt.Println()
  138. }
  139. // Head returns a pointer to the first node of the list
  140. func (ll *ItemLinkedList) Head() *Node {
  141. ll.lock.RLock()
  142. defer ll.lock.RUnlock()
  143. return ll.head
  144. }