linked_list.jl 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. # StarPU --- Runtime system for heterogeneous multicore architectures.
  2. #
  3. # Copyright (C) 2020 Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria
  4. #
  5. # StarPU is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU Lesser General Public License as published by
  7. # the Free Software Foundation; either version 2.1 of the License, or (at
  8. # your option) any later version.
  9. #
  10. # StarPU is distributed in the hope that it will be useful, but
  11. # WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. #
  14. # See the GNU Lesser General Public License in COPYING.LGPL for more details.
  15. #
  16. export Link
  17. mutable struct Link{T}
  18. data :: T
  19. previous :: Union{Nothing, Link{T}}
  20. next :: Union{Nothing, Link{T}}
  21. list
  22. function Link{T}(x :: T, l) where {T}
  23. output = new()
  24. output.data = x
  25. output.previous = Nothing()
  26. output.next = Nothing()
  27. output.list = l
  28. return output
  29. end
  30. end
  31. export LinkedList
  32. mutable struct LinkedList{T}
  33. nelement :: Int64
  34. first :: Union{Nothing, Link{T}}
  35. last :: Union{Nothing, Link{T}}
  36. function LinkedList{T}() where {T}
  37. output = new()
  38. output.nelement = 0
  39. output.first = Nothing()
  40. output.last = Nothing()
  41. return output
  42. end
  43. end
  44. export add_to_head!
  45. function add_to_head!(l :: LinkedList{T}, el :: T) where {T}
  46. new_first = Link{T}(el, l)
  47. old_first = l.first
  48. l.first = new_first
  49. new_first.next = old_first
  50. if (isnothing(old_first))
  51. l.last = new_first
  52. else
  53. old_first.previous = new_first
  54. end
  55. l.nelement += 1
  56. return new_first
  57. end
  58. export add_to_tail!
  59. function add_to_tail!(l :: LinkedList{T}, el :: T) where {T}
  60. new_last = Link{T}(el, l)
  61. old_last = l.last
  62. l.last = new_last
  63. new_last.previous = old_last
  64. if (isnothing(old_last))
  65. l.first = new_last
  66. else
  67. old_last.next = new_last
  68. end
  69. l.nelement += 1
  70. return new_last
  71. end
  72. function LinkedList(v :: Union{Array{T,N}, NTuple{N,T}}) where {N,T}
  73. output = LinkedList{T}()
  74. for x in v
  75. add_to_tail!(output, x)
  76. end
  77. return output
  78. end
  79. export remove_link!
  80. function remove_link!(lnk :: Link{T}) where {T}
  81. if (lnk.list == nothing)
  82. return lnk.data
  83. end
  84. l = lnk.list
  85. next = lnk.next
  86. previous = lnk.previous
  87. if (isnothing(next))
  88. l.last = previous
  89. else
  90. next.previous = previous
  91. end
  92. if (isnothing(previous))
  93. l.first = next
  94. else
  95. previous.next = next
  96. end
  97. l.nelement -= 1
  98. lnk.list = nothing
  99. return lnk.data
  100. end
  101. export is_linked
  102. function is_linked(lnk :: Link)
  103. return (lnk.list != nothing)
  104. end
  105. export foreach_asc
  106. macro foreach_asc(list, lnk_iterator, expression)
  107. quote
  108. $(esc(lnk_iterator)) = $(esc(list)).first
  109. while (!isnothing($(esc(lnk_iterator))))
  110. __next_lnk_iterator = $(esc(lnk_iterator)).next
  111. $(esc(expression))
  112. $(esc(lnk_iterator)) = __next_lnk_iterator
  113. end
  114. end
  115. end
  116. export foreach_desc
  117. macro foreach_desc(list, lnk_iterator, expression)
  118. quote
  119. $(esc(lnk_iterator)) = $(esc(list)).last
  120. while (!isnothing($(esc(lnk_iterator))))
  121. __next_lnk_iterator = $(esc(lnk_iterator)).previous
  122. $(esc(expression))
  123. $(esc(lnk_iterator)) = __next_lnk_iterator
  124. end
  125. end
  126. end
  127. function Base.show(io :: IO, lnk :: Link{T}) where {T}
  128. print(io, "Link{$T}{data: ")
  129. print(io, lnk.data)
  130. print(io, " ; previous: ")
  131. if (isnothing(lnk.previous))
  132. print(io, "NONE")
  133. else
  134. print(io, lnk.previous.data)
  135. end
  136. print(io, " ; next: ")
  137. if (isnothing(lnk.next))
  138. print(io, "NONE")
  139. else
  140. print(io, lnk.next.data)
  141. end
  142. print(io, "}")
  143. end
  144. function Base.show(io :: IO, l :: LinkedList{T}) where {T}
  145. print(io, "LinkedList{$T}{")
  146. @foreach_asc l lnk begin
  147. if (!isnothing(lnk.previous))
  148. print(io, ", ")
  149. end
  150. print(io, lnk.data)
  151. end
  152. print(io, "}")
  153. end
  154. #import Base.start
  155. function start(l :: LinkedList)
  156. return nothing
  157. end
  158. #import Base.done
  159. function done(l :: LinkedList, state)
  160. if (state == nothing)
  161. return isnothing(l.first)
  162. end
  163. return isnothing(state.next)
  164. end
  165. #import Base.next
  166. function next(l :: LinkedList, state)
  167. if (state == nothing)
  168. next_link = l.first
  169. else
  170. next_link = state.next
  171. end
  172. return (next_link.data, next_link)
  173. end
  174. #import Base.endof
  175. function endof(l :: LinkedList)
  176. return l.nelement
  177. end
  178. export index_to_link
  179. function index_to_link(l :: LinkedList, ind)
  180. if (ind > l.nelement || ind <= 0)
  181. error("Invalid index")
  182. end
  183. lnk = l.first
  184. for i in (1:(ind - 1))
  185. lnk = lnk.next
  186. end
  187. return lnk
  188. end
  189. import Base.getindex
  190. function getindex(l :: LinkedList, ind)
  191. return index_to_link(l,ind).data
  192. end
  193. import Base.setindex!
  194. function setindex!(l :: LinkedList{T}, ind, value :: T) where T
  195. lnk = index_to_link(l,ind)
  196. lnk.data = value
  197. end
  198. import Base.eltype
  199. function eltype(l :: LinkedList{T}) where T
  200. return T
  201. end
  202. import Base.isempty
  203. function isempty(l :: LinkedList)
  204. return (l.nelement == 0)
  205. end
  206. import Base.empty!
  207. function empty!(l :: LinkedList)
  208. @foreach_asc l lnk remove_link!(lnk)
  209. end
  210. import Base.length
  211. function length(l :: LinkedList)
  212. return l.nelement
  213. end