linked_list.jl 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. export Link
  2. mutable struct Link{T}
  3. data :: T
  4. previous :: Union{Nothing, Link{T}}
  5. next :: Union{Nothing, Link{T}}
  6. list
  7. function Link{T}(x :: T, l) where {T}
  8. output = new()
  9. output.data = x
  10. output.previous = Nothing()
  11. output.next = Nothing()
  12. output.list = l
  13. return output
  14. end
  15. end
  16. export LinkedList
  17. mutable struct LinkedList{T}
  18. nelement :: Int64
  19. first :: Union{Nothing, Link{T}}
  20. last :: Union{Nothing, Link{T}}
  21. function LinkedList{T}() where {T}
  22. output = new()
  23. output.nelement = 0
  24. output.first = Nothing()
  25. output.last = Nothing()
  26. return output
  27. end
  28. end
  29. export add_to_head!
  30. function add_to_head!(l :: LinkedList{T}, el :: T) where {T}
  31. new_first = Link{T}(el, l)
  32. old_first = l.first
  33. l.first = new_first
  34. new_first.next = old_first
  35. if (isnothing(old_first))
  36. l.last = new_first
  37. else
  38. old_first.previous = new_first
  39. end
  40. l.nelement += 1
  41. return new_first
  42. end
  43. export add_to_tail!
  44. function add_to_tail!(l :: LinkedList{T}, el :: T) where {T}
  45. new_last = Link{T}(el, l)
  46. old_last = l.last
  47. l.last = new_last
  48. new_last.previous = old_last
  49. if (isnothing(old_last))
  50. l.first = new_last
  51. else
  52. old_last.next = new_last
  53. end
  54. l.nelement += 1
  55. return new_last
  56. end
  57. function LinkedList(v :: Union{Array{T,N}, NTuple{N,T}}) where {N,T}
  58. output = LinkedList{T}()
  59. for x in v
  60. add_to_tail!(output, x)
  61. end
  62. return output
  63. end
  64. export remove_link!
  65. function remove_link!(lnk :: Link{T}) where {T}
  66. if (lnk.list == nothing)
  67. return lnk.data
  68. end
  69. l = lnk.list
  70. next = lnk.next
  71. previous = lnk.previous
  72. if (isnothing(next))
  73. l.last = previous
  74. else
  75. next.previous = previous
  76. end
  77. if (isnothing(previous))
  78. l.first = next
  79. else
  80. previous.next = next
  81. end
  82. l.nelement -= 1
  83. lnk.list = nothing
  84. return lnk.data
  85. end
  86. export is_linked
  87. function is_linked(lnk :: Link)
  88. return (lnk.list != nothing)
  89. end
  90. export foreach_asc
  91. macro foreach_asc(list, lnk_iterator, expression)
  92. quote
  93. $(esc(lnk_iterator)) = $(esc(list)).first
  94. while (!isnothing($(esc(lnk_iterator))))
  95. __next_lnk_iterator = $(esc(lnk_iterator)).next
  96. $(esc(expression))
  97. $(esc(lnk_iterator)) = __next_lnk_iterator
  98. end
  99. end
  100. end
  101. export foreach_desc
  102. macro foreach_desc(list, lnk_iterator, expression)
  103. quote
  104. $(esc(lnk_iterator)) = $(esc(list)).last
  105. while (!isnothing($(esc(lnk_iterator))))
  106. __next_lnk_iterator = $(esc(lnk_iterator)).previous
  107. $(esc(expression))
  108. $(esc(lnk_iterator)) = __next_lnk_iterator
  109. end
  110. end
  111. end
  112. function Base.show(io :: IO, lnk :: Link{T}) where {T}
  113. print(io, "Link{$T}{data: ")
  114. print(io, lnk.data)
  115. print(io, " ; previous: ")
  116. if (isnothing(lnk.previous))
  117. print(io, "NONE")
  118. else
  119. print(io, lnk.previous.data)
  120. end
  121. print(io, " ; next: ")
  122. if (isnothing(lnk.next))
  123. print(io, "NONE")
  124. else
  125. print(io, lnk.next.data)
  126. end
  127. print(io, "}")
  128. end
  129. function Base.show(io :: IO, l :: LinkedList{T}) where {T}
  130. print(io, "LinkedList{$T}{")
  131. @foreach_asc l lnk begin
  132. if (!isnothing(lnk.previous))
  133. print(io, ", ")
  134. end
  135. print(io, lnk.data)
  136. end
  137. print(io, "}")
  138. end
  139. #import Base.start
  140. function start(l :: LinkedList)
  141. return nothing
  142. end
  143. #import Base.done
  144. function done(l :: LinkedList, state)
  145. if (state == nothing)
  146. return isnothing(l.first)
  147. end
  148. return isnothing(state.next)
  149. end
  150. #import Base.next
  151. function next(l :: LinkedList, state)
  152. if (state == nothing)
  153. next_link = l.first
  154. else
  155. next_link = state.next
  156. end
  157. return (next_link.data, next_link)
  158. end
  159. #import Base.endof
  160. function endof(l :: LinkedList)
  161. return l.nelement
  162. end
  163. export index_to_link
  164. function index_to_link(l :: LinkedList, ind)
  165. if (ind > l.nelement || ind <= 0)
  166. error("Invalid index")
  167. end
  168. lnk = l.first
  169. for i in (1:(ind - 1))
  170. lnk = lnk.next
  171. end
  172. return lnk
  173. end
  174. import Base.getindex
  175. function getindex(l :: LinkedList, ind)
  176. return index_to_link(l,ind).data
  177. end
  178. import Base.setindex!
  179. function setindex!(l :: LinkedList{T}, ind, value :: T) where T
  180. lnk = index_to_link(l,ind)
  181. lnk.data = value
  182. end
  183. import Base.eltype
  184. function eltype(l :: LinkedList{T}) where T
  185. return T
  186. end
  187. import Base.isempty
  188. function isempty(l :: LinkedList)
  189. return (l.nelement == 0)
  190. end
  191. import Base.empty!
  192. function empty!(l :: LinkedList)
  193. @foreach_asc l lnk remove_link!(lnk)
  194. end
  195. import Base.length
  196. function length(l :: LinkedList)
  197. return l.nelement
  198. end