• By Golang

    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. }