BAH!
4. The "intrusive" containers, but of course.
The one true way to do it in C.
For one, you can keep items in multiple containers, all being on equal footing. None of that typical C++ mess, when this list is a primary storage for items, and those maps are secondary indexes, all sprinkled evenly with iterators. Intrusive containers don't own items, they merely organize them, which is exactly the right way to go about it.
For two, the actual code for container operations is as abstract and on-point as it gets as it focuses solely on "weaving" items into and out of a container rather than on other things, like de/allocating supporting structures.
For three, you get no heap activity when adding/removing items to/from a container. This means that if you already have the items, you can always arrange them into a collection. This also eliminates a lot of error handling code, leading to a simpler code.
Obviously, this is not limited to just linked lists.
[1] http://www.makelinux.net/ldd3/chp-11-sect-5 (