Table of Contents
While a singly linked list stores data and the pointer to the next node, a doubly-linked list, on the other hand, has slots to store data, address of the previous node, and address of the next node. A doubly linked list allows us to perform operations like deletion and insertion more efficiently. We can also traverse the list in both directions. However, it takes more space than the singly linked list.
We can make it more memory efficient by using the XOR linked list. It works the same as the doubly linked list, but it uses a single slot to store addresses for the next and previous nodes. It does that by taking the bitwise XOR (^) of both addresses. It is also known as a memory-efficient doubly linked list.
To understand how this is possible, let’s look at the properties of XOR first.
| A^B | B^A |
| A^(B^C) | (A^B)^C |
| 0^A | A |
| A^A | 0 |
Traversal in XOR Linked List
Since it works like a doubly-linked list, we can traverse the list in both directions. First, let’s consider traversal from left to right. One thing to note here is that, at some node N, we have access to its previous node since we are going from left to right. Moreover, we have three types of nodes to consider, i.e., the first node, middle, and the last node.
The formula to get the next node is as follows:
addr (next) = addr(prev)^addr(XOR value at current node)
When we are at the first node A, it contains the XOR of NULL (previous node) and B (next node), i.e., 0^addr(B). The address of the next node can be found as follows:
addr(next) = 0^(0^addr(B)) addr(next) = 0^(addr(B)) addr(next) = addr(B)
When we are at some middle node B, it contains the XOR of A(previous node) and C (next node), i.e., addr(A)^addr(C).
addr(next) = addr(A)^(addr(A)^addr(C)) addr(next) = (addr(A)^ addr(A))^addr(C) addr(next) = 0^addr(C) addr(next) = addr(C)
The last node C contains the XOR of B(previous node) and NULL (next node), i.e., addr(B)^0.
addr(next) = addr(B)^(addr(B)^0) addr(next) = addr(B)^addr(B) Addr(next) = 0
We can perform the traversal from right to left in a similar manner, except we start from the tail, i.e., node C.
Implementation
The following implementation of the XOR Linked List contains the following functionalities.
Insert
It adds a node at the start of the XOR linked list. If the list is empty, it just creates a node with the given value, and the xor address value (xadd) is set to 0 since it is the only node. Otherwise, it creates a node with xadd value equal to the XOR of 0 (NULL) and the current head’s address. xadd value of the current head gets updated to the XOR of the address of the new node and the node’s address after the current head. Moreover, the new node becomes the head now.
Delete
It removes the first item from the list and returns the deleted data. First, it checks if the list is empty or not. If it is not, then it finds the next node. If the next node does not exist, then it sets the head and tail pointer to NULL. Otherwise, its xadd value gets updated to the address of the node after that, i.e., addr(current head)^(xadd value of the next node). The next node becomes the head now.
LR_traversal
It traverses the list in the forward direction.
RL_traversal
It traverses the list in the backward direction.
The code is given below.
import _ctypes
class Node:
def __init__(self, value, xadd=0):
self.value = value #data
self.xadd = xadd # XOR of the address of the previous node and address of the next node
class XORLinkedlList:
def __init__(self):
self.head=None
self.tail = None
self.nodes = []
#adds an item at the beginning of the list
def insert(self, value):
if self.head == None: #node to be inserted is the first node
self.head = Node(value)
self.tail = self.head
else:
new_node = Node(value, 0^id(self.head)) #create new node with xadd value equal to address of the next node
self.head.xadd = id(new_node)^self.head.xadd #update the xadd value of the current head to the XOR of addresses of previous and next nodes
self.head = new_node #update the head
self.nodes.append(self.head)
#deletes an item from the beginning of the list
def delete(self):
if self.head:
del_val = self.head.value
next_node = 0^self.head.xadd #find the address of the next node
if next_node:
next_node = _ctypes.PyObj_FromPtr(next_node) #get the node placed at the given address
next_node.xadd = id(self.head)^(next_node.xadd) #update the next node xadd value to the address of the node after that
self.head = next_node #change the head
else:
self.head = None
self.tail = None
self.nodes.pop().value
return del_val
#print list items in the forward direction
def LR_traversal(self):
if self.head:
curr_node = id(self.head) #get the address of the first node
prev_node = 0
while curr_node:
curr_node = _ctypes.PyObj_FromPtr(curr_node) #get the node placed at the given address
print(curr_node.value, end=" ") #display the value of the current node
next = prev_node^(curr_node.xadd) #get the address of the next node
#update the current and previous nodes
prev_node = id(curr_node)
curr_node = next
#print list items in the backward direction
def RL_traversal(self):
if self.head:
curr_node = id(self.tail) #get the address of the last node
prev_node = 0
while curr_node:
curr_node = _ctypes.PyObj_FromPtr(curr_node) #get the node placed at the given address
print(curr_node.value, end=" ") #display the value of the current node
next = prev_node^(curr_node.xadd) #get the address of the next node
#update the current and previous nodes
prev_node = id(curr_node)
curr_node = next
ll = XORLinkedlList()
ll.insert(2)
ll.insert(3)
ll.insert(1)
ll.insert(5)
print("Left to Right Traversal of the XOR Linked List")
ll.LR_traversal()
print("\nRight to Left Traversal of the XOR Linked List")
ll.RL_traversal()
print("\nDeleted Value:",ll.delete())
print("Deleted Value:",ll.delete())
print("Left to Right Traversal of the XOR Linked List")
ll.LR_traversal()
print("\nRight to Left Traversal of the XOR Linked List")
ll.RL_traversal()
Output
Left to Right Traversal of the XOR Linked List 5 1 3 2 Right to Left Traversal of the XOR Linked List 2 3 1 5 Deleted Value: 5 Deleted Value: 1 Left to Right Traversal of the XOR Linked List 3 2 Right to Left Traversal of the XOR Linked List 2 3

