1
1
module datatypes
2
2
3
+ @[heap]
3
4
pub struct ListNode [T] {
4
5
mut :
5
6
data T
6
- next & ListNode[T] = unsafe { 0 }
7
+ next & ListNode[T] = unsafe { nil }
7
8
}
8
9
10
+ @[heap]
9
11
pub struct LinkedList [T] {
10
12
mut :
11
- head & ListNode[T] = unsafe { 0 }
13
+ head & ListNode[T] = unsafe { nil }
14
+ tail & ListNode[T] = unsafe { nil }
12
15
len int
13
16
// Internal iter pointer for allowing safe modification
14
17
// of the list while iterating. TODO: use an option
15
18
// instead of a pointer to determine if it is initialized.
16
- iter & ListIter[T] = unsafe { 0 }
19
+ iter & ListIter[T] = unsafe { nil }
17
20
}
18
21
19
22
// is_empty checks if the linked list is empty
23
+ @[inline]
20
24
pub fn (list LinkedList[T]) is_empty () bool {
21
25
return list.len == 0
22
26
}
23
27
24
28
// len returns the length of the linked list
29
+ @[inline]
25
30
pub fn (list LinkedList[T]) len () int {
26
31
return list.len
27
32
}
28
33
29
34
// first returns the first element of the linked list
35
+ @[inline]
30
36
pub fn (list LinkedList[T]) first () ! T {
31
37
return if ! list.is_empty () { list.head.data } else { error ('Linked list is empty' ) }
32
38
}
33
39
34
40
// last returns the last element of the linked list
41
+ @[inline]
35
42
pub fn (list LinkedList[T]) last () ! T {
36
- if unsafe { list.head == 0 } {
37
- return error ('Linked list is empty' )
38
- } else {
39
- mut node := list.head
40
- for unsafe { node.next != 0 } {
41
- node = node.next
42
- }
43
- return node.data
44
- }
43
+ return if ! list.is_empty () { list.tail.data } else { error ('Linked list is empty' ) }
45
44
}
46
45
47
46
// index returns the element at the given index of the linked list
48
47
pub fn (list LinkedList[T]) index (idx int ) ! T {
49
- if unsafe { list.head == 0 } {
48
+ if list.is_empty () {
50
49
return error ('Linked list is empty' )
51
- } else {
52
- mut node := list.head
53
- mut iterations := 0
54
- for unsafe { node.next != 0 } && iterations < idx {
55
- node = node.next
56
- iterations++
57
- }
58
- if iterations == idx {
59
- return node.data
60
- } else {
61
- return error ('Index ${idx} != iterations: ${iterations} ' )
62
- }
63
50
}
51
+ if idx < 0 || idx > = list.len {
52
+ return error ('Index ${idx} out of bounds' )
53
+ }
54
+ mut node := list.head
55
+ for _ in 0 .. idx {
56
+ node = node.next
57
+ }
58
+ return node.data
64
59
}
65
60
66
61
// push adds an element to the end of the linked list
67
62
pub fn (mut list LinkedList[T]) push (item T) {
68
63
new_node := & ListNode[T]{
69
64
data: item
70
65
}
71
- if unsafe { list.head == 0 } {
66
+ if list.is_empty () {
72
67
// first node case
73
68
list.head = new_node
74
69
} else {
75
- mut node := list.head
76
- for unsafe { node.next != 0 } {
77
- node = node.next
78
- }
79
- node.next = new_node
70
+ list.tail.next = new_node
80
71
}
72
+ list.tail = new_node
81
73
list.len + = 1
82
74
}
83
75
@@ -90,35 +82,40 @@ pub fn (mut list LinkedList[T]) push_many(elements []T) {
90
82
91
83
// pop removes the last element of the linked list
92
84
pub fn (mut list LinkedList[T]) pop () ! T {
93
- if unsafe { list.head == 0 } {
85
+ if list.is_empty () {
94
86
return error ('Linked list is empty' )
95
87
}
96
88
mut node := list.head
97
89
mut to_return := unsafe { node.data }
98
- if unsafe { node.next == 0 } {
90
+ if isnil ( node.next) {
99
91
// first node case
100
92
// set to null
101
93
list.head = unsafe { nil }
94
+ list.tail = unsafe { nil }
102
95
} else {
103
- for unsafe { node.next.next != 0 } {
96
+ for ! isnil ( node.next.next) {
104
97
node = node.next
105
98
}
106
99
to_return = unsafe { node.next.data }
107
100
// set to null
108
101
node.next = unsafe { nil }
102
+ list.tail = node
109
103
}
110
104
list.len - = 1
111
105
return to_return
112
106
}
113
107
114
108
// shift removes the first element of the linked list
115
109
pub fn (mut list LinkedList[T]) shift () ! T {
116
- if unsafe { list.head == 0 } {
110
+ if list.is_empty () {
117
111
return error ('Linked list is empty' )
118
112
} else {
119
113
list.len - = 1
120
114
node := list.head
121
115
list.head = node.next
116
+ if list.is_empty () {
117
+ list.tail = unsafe { nil }
118
+ }
122
119
return node.data
123
120
}
124
121
}
@@ -127,28 +124,36 @@ pub fn (mut list LinkedList[T]) shift() !T {
127
124
pub fn (mut list LinkedList[T]) insert (idx int , item T) ! {
128
125
if idx < 0 || idx > list.len {
129
126
return error ('Index ${idx} out of bounds [0..${list.len} ]' )
130
- } else if list.len == 0 {
127
+ }
128
+ if idx == list.len {
131
129
list.push (item)
130
+ return
131
+ }
132
+ mut new_node := & ListNode[T]{
133
+ data: item
134
+ }
135
+ if list.is_empty () {
136
+ list.head = new_node
137
+ list.tail = new_node
132
138
} else {
133
- list.len + = 1
134
139
mut node := list.head
135
140
136
141
if idx == 0 {
137
142
// first node case
138
- list.head = & ListNode[T]{
139
- data: item
140
- next: node
141
- }
143
+ new_node.next = node
144
+ list.head = new_node
142
145
} else {
143
146
for i := 0 ; i < idx - 1 ; i++ {
144
147
node = node.next
145
148
}
146
- node.next = & ListNode[T]{
147
- data: item
148
- next: node.next
149
+ new_node.next = node.next
150
+ node.next = new_node
151
+ if isnil (new_node.next) {
152
+ list.tail = new_node
149
153
}
150
154
}
151
155
}
156
+ list.len + = 1
152
157
}
153
158
154
159
// prepend adds an element to the beginning of the linked list (equivalent to insert(0, item))
@@ -165,7 +170,7 @@ pub fn (list LinkedList[T]) str() string {
165
170
pub fn (list LinkedList[T]) array () []T {
166
171
mut result_array := []T{cap: list.len}
167
172
mut node := list.head
168
- for unsafe { node != 0 } {
173
+ for ! isnil (node) {
169
174
result_array << node.data
170
175
node = node.next
171
176
}
@@ -175,14 +180,14 @@ pub fn (list LinkedList[T]) array() []T {
175
180
// next implements the iteration interface to use LinkedList
176
181
// with V's `for` loop syntax.
177
182
pub fn (mut list LinkedList[T]) next () ? T {
178
- if list.iter == unsafe { nil } {
183
+ if isnil ( list.iter) {
179
184
// initialize new iter object
180
185
list.iter = & ListIter[T]{
181
186
node: list.head
182
187
}
183
188
return list.next ()
184
189
}
185
- if list.iter.node == unsafe { nil } {
190
+ if isnil ( list.iter.node) {
186
191
list.iter = unsafe { nil }
187
192
return none
188
193
}
@@ -205,13 +210,13 @@ pub fn (mut list LinkedList[T]) iterator() ListIter[T] {
205
210
// An iterator instance always traverses the list from start to finish.
206
211
pub struct ListIter [T] {
207
212
mut :
208
- node & ListNode[T] = unsafe { 0 }
213
+ node & ListNode[T] = unsafe { nil }
209
214
}
210
215
211
216
// next returns the next element of the list, or `none` when the end of the list is reached.
212
217
// It is called by V's `for x in iter{` on each iteration.
213
218
pub fn (mut iter ListIter[T]) next () ? T {
214
- if iter.node == unsafe { nil } {
219
+ if isnil ( iter.node) {
215
220
return none
216
221
}
217
222
res := unsafe { iter.node.data }
0 commit comments