I know this is my second answer, but I think the explanation I am giving here may be better than the last answer. But note that even this answer is correct.
A efficient memory-related list is most often called the XOR Linked List , since it is completely dependent on the logical Gate XOR and its properties.
Is it different from a doubly linked list?
Yes it is. It actually does almost the same job as the Doubly Linked List, but it is different.
A Doubly-Linked List stores two pointers that point to the next and previous node. Basically, if you want to return, you will go to the address indicated by the back pointer. If you want to go forward, you go to the address indicated by the next pointer. Like it:

A memory-linked list of links , namely the XOR linked list has only one pointer instead of two. This stores the previous address (addr (prev)) XOR (^) the next address (addr (next)). When you want to move to the next node, you perform certain calculations and find the address of the next node. This is the same for going to the previous node. It looks like:

How it works?
The linked XOR list , as you can see from its name, is highly dependent on the XOR (^) logic element and its properties.
Its properties:
|-------------|------------|------------| | Name | Formula | Result | |-------------|------------|------------| | Commutative | A ^ B | B ^ A | |-------------|------------|------------| | Associative | A ^ (B ^ C)| (A ^ B) ^ C| |-------------|------------|------------| | None (1) | A ^ 0 | A | |-------------|------------|------------| | None (2) | A ^ A | 0 | |-------------|------------|------------| | None (3) | (A ^ B) ^ A| B | |-------------|------------|------------|
Now leave that aside and see what each node stores:
The first node or head stores 0 ^ addr (next) , since there is no previous node or address. It looks like this:

Then the second node stores addr (prev) ^ addr (next) . It looks like this:

The figure above shows node B, or the second node. A and C are the address of the third and first node. All node except the head and tail, like the previous ones.
the tail of the list does not have the next node, so it saves addr (prev) ^ 0 . It looks like this:

Before we see how we are moving, we will again see a view of the linked XOR list:

When you see

this clearly means that there is one link field with which you move back and forth.
Also, note that when using a linked XOR list, you need to have a temporary variable (not in node) that stores the address of the node you were in before. When you move to the next node, you discard the old value and keep the address of the node that you were before.
Going from chapter to next node
Say you are now on the first node or in node A. Now you want to switch to node B. This is the formula for this:
Address of Next Node = Address of Previous Node ^ pointer in the current Node
So this will be:
addr (next) = addr (prev) ^ (0 ^ addr (next))
Since this is the head, the previous address would be just 0, therefore:
addr (next) = 0 ^ (0 ^ addr (next))
We can remove the parentheses:
addr (next) = 0 ^ 0 addr (next)
Using the none (2) property, we can say that 0 ^ 0 will always be 0:
addr (next) = 0 ^ addr (next)
Using the none (1) property, we can simplify it:
addr (next) = addr (next)
You have received the address of the next node!
Going from node to next node
Now let's say that we are in the middle of the node, which has the previous and next node.
We apply the formula:
Address of Next Node = Address of Previous Node ^ pointer in the current Node
Now replace the values:
addr (next) = addr (prev) ^ (addr (prev) ^ addr (next))
Remove parentheses:
addr (next) = addr (prev) ^ addr (prev) ^ addr (next)
Using the none (2) property, we can simplify:
addr (next) = 0 ^ addr (next)
Using the none (1) property, we can simplify:
addr (next) = addr (next)
And get it!
Moving from node to node, you were in the previous
If you don’t understand the title, it basically means that if you were in node X and now moved to node Y, you want to return to the node you visited earlier, or basically node X.
This is not a cumbersome task. Remember that I mentioned above that you are storing the address at which you were in the temporary variable. So the node address you want to visit lies in the variable:
addr (prev) = temp_addr
Go from node to previous node
This is not the same as above. I want to say that you were in node Z, now you are in node Y and want to go to node X.
This is almost the same as moving from node to next node. It's just the opposite. When you write a program, you will use the same steps that I mentioned when moving from one node to the next node, just so that you find an earlier item in the list than searching for the next item.
I don’t think I need to explain this.
Benefits of XOR Linked List
This uses less memory than the Doubly Linked List . Approximately 33% less.
Only one pointer is used. This simplifies the structure of the node.
As doinax said, the XOR submode can be reversed in time.
Disadvantages of XOR Linked List
This is a little difficult to implement. It has a higher chance of failure, and debugging is rather complicated.
All conversions (in case of int) should be performed in / from uintptr_t
You cannot just get the node address and start moving (or something else) from there. You should always start with the head or tail.
You cannot jump or skip nodes. You have to go one by one.
More operations are required to move.
It is difficult to debug a program using a linked XOR list. It is much easier to debug a double list.
References