authorgravatar for quae@daurnimator.comdaurnimator <quae@daurnimator.com> 2018-11-17 21:17:47+11:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-11-29 09:44:24-05:00
log4ecb3ceafb7e82f1d2b44059b9bbb266aa1dce00
tree5d1724210f6a40745be6d8d9612884fb1a61967e
parent7005ec5efea6d261b6fc6fef84389f528fc6b472

Add std.LinkedList.concat


1 files changed, 96 insertions(+), 0 deletions(-)

std/linked_list.zig+96
...@@ -82,6 +82,28 @@ pub fn LinkedList(comptime T: type) type {...@@ -82,6 +82,28 @@ pub fn LinkedList(comptime T: type) type {
82 list.len += 1;82 list.len += 1;
83 }83 }
8484
85 /// Concatenate list2 onto the end of list1, removing all entries from the former.
86 ///
87 /// Arguments:
88 /// list1: the list to concatenate onto
89 /// list2: the list to be concatenated
90 pub fn concatByMoving(list1: *Self, list2: *Self) void {
91 const l2_first = list2.first orelse return;
92 if (list1.last) |l1_last| {
93 l1_last.next = list2.first;
94 l2_first.prev = list1.last;
95 list1.len += list2.len;
96 } else {
97 // list1 was empty
98 list1.first = list2.first;
99 list1.len = list2.len;
100 }
101 list1.last = list2.last;
102 list2.first = null;
103 list2.last = null;
104 list2.len = 0;
105 }
106
85 /// Insert a new node at the end of the list.107 /// Insert a new node at the end of the list.
86 ///108 ///
87 /// Arguments:109 /// Arguments:
...@@ -247,3 +269,77 @@ test "basic linked list test" {...@@ -247,3 +269,77 @@ test "basic linked list test" {
247 assert(list.last.?.data == 4);269 assert(list.last.?.data == 4);
248 assert(list.len == 2);270 assert(list.len == 2);
249}271}
272
273test "linked list concatenation" {
274 const allocator = debug.global_allocator;
275 var list1 = LinkedList(u32).init();
276 var list2 = LinkedList(u32).init();
277
278 var one = try list1.createNode(1, allocator);
279 defer list1.destroyNode(one, allocator);
280 var two = try list1.createNode(2, allocator);
281 defer list1.destroyNode(two, allocator);
282 var three = try list1.createNode(3, allocator);
283 defer list1.destroyNode(three, allocator);
284 var four = try list1.createNode(4, allocator);
285 defer list1.destroyNode(four, allocator);
286 var five = try list1.createNode(5, allocator);
287 defer list1.destroyNode(five, allocator);
288
289 list1.append(one);
290 list1.append(two);
291 list2.append(three);
292 list2.append(four);
293 list2.append(five);
294
295 list1.concatByMoving(&list2);
296
297 assert(list1.last == five);
298 assert(list1.len == 5);
299 assert(list2.first == null);
300 assert(list2.last == null);
301 assert(list2.len == 0);
302
303 // Traverse forwards.
304 {
305 var it = list1.first;
306 var index: u32 = 1;
307 while (it) |node| : (it = node.next) {
308 assert(node.data == index);
309 index += 1;
310 }
311 }
312
313 // Traverse backwards.
314 {
315 var it = list1.last;
316 var index: u32 = 1;
317 while (it) |node| : (it = node.prev) {
318 assert(node.data == (6 - index));
319 index += 1;
320 }
321 }
322
323 // Swap them back, this verifies that concating to an empty list works.
324 list2.concatByMoving(&list1);
325
326 // Traverse forwards.
327 {
328 var it = list2.first;
329 var index: u32 = 1;
330 while (it) |node| : (it = node.next) {
331 assert(node.data == index);
332 index += 1;
333 }
334 }
335
336 // Traverse backwards.
337 {
338 var it = list2.last;
339 var index: u32 = 1;
340 while (it) |node| : (it = node.prev) {
341 assert(node.data == (6 - index));
342 index += 1;
343 }
344 }
345}