Skip to content

Instantly share code, notes, and snippets.

@LouiseBC
Last active September 7, 2025 17:51
Show Gist options
  • Save LouiseBC/692bfd907d9e0527b471947d540dee6c to your computer and use it in GitHub Desktop.
Save LouiseBC/692bfd907d9e0527b471947d540dee6c to your computer and use it in GitHub Desktop.
-- Circular, doubly linked list --
----------------------------------
local linkedList = {}
-- Creates a list from table or variable n. of values --
function linkedList.construct(...)
local args = {...}
local tail = linkedList.newNode(args[1])
for i = 2, #args do
linkedList.insert(tail, args[i])
tail = tail.next
end
return tail.next
end
-- Creates a new instance of node --
function linkedList.newNode(val)
local node = {}
node.value = val
node.next = node
node.prev = node
return node
end
-- Inserts a node after the given node && returns a reference --
function linkedList.insert(node, val)
local newnode = linkedList.newNode(val)
newnode.next = node.next
newnode.prev = node
node.next = newnode
return newnode
end
-- Remove an element of the list, return reference to next element --
function linkedList.erase(node)
local index = node.next
node.prev.next = node.next
node = nil
return index
end
-- Print the whole list, avoiding circularity --
function linkedList.print(node)
local it = node
repeat
print(it.value)
it = it.next
until it == node
end
return linkedList
local list = require("LinkedList")
foo = list.construct(1, 2, 3, 4, 5, 6)
list.print(foo) print()
-- Output: 1, 2, 3, 4, 5, 6 --
list.print(foo.next.next) print()
-- Output: 3, 4, 5, 6, 1, 2 --
last = list.insert(foo.prev, 'bar')
list.print(last) print()
-- Output: 'bar', 2, 3, 4, 5, 6, 1
-- Oops: first in list doesn't refer to last --
-- Don't know how to do this without storing additional information --
last = list.erase(last)
list.print(last)
-- Output: 2, 3, 4, 5, 6, 1
@stegrams
Copy link

stegrams commented Sep 7, 2025

For all of you visiting this, two years old, gist, the problem is that the construct function is not updating the head about the current last item the insert and the erase functions do not update both the adjacent nodes.

Also, I think that clearing the links of the erased node is a good thing for the garbage collector.

The solution is to add after the line 13 the following update them as:

  -- Ignore this.
  -- tail.next.prev = tail

-- Inserts a node after the given node && returns a reference --
function linkedList.insert(node, val)
  local newnode = linkedList.newNode(val)
  newnode.next = node.next
  newnode.next.prev = newnode
  newnode.prev = node
  newnode.prev.next = newnode
  return newnode
end

-- Remove an element of the list, return reference to next element --
function linkedList.erase(node)
  local head = node.next
  node.prev.next = node.next
  node.next.prev = node.prev
  node.prev, node.next = nil, nil
  return head
end

Not tested thoroughly though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment