11"""
22XOR Linked List implementation
3-
43A memory-efficient doubly linked list using XOR of node addresses.
54Each node stores one pointer that is the XOR of previous and next node addresses.
6-
75Example:
86>>> xor_list = XORLinkedList()
97>>> xor_list.insert(10)
1311[10, 20, 30]
1412"""
1513
16- from typing import Optional
14+ # Note: This implementation simulates pointer behavior using Python's id()
15+ # and a dictionary lookup (_nodes). In languages like C, this would
16+ # be done with actual memory addresses and pointer arithmetic.
1717
1818
1919class Node :
20- def __init__ (self , value : int ) -> None :
20+ def __init__ (self , value : int ):
2121 self .value = value
2222 self .both : int = 0 # XOR of prev and next node ids
2323
2424
2525class XORLinkedList :
26- def __init__ (self ) -> None :
27- self .head : Optional [Node ] = None
28- self .tail : Optional [Node ] = None
29- self ._nodes = {} # id → node map to simulate pointer references
26+ def __init__ (self ):
27+ # Use 'Node | None' instead of 'Optional[Node]' (per ruff UP045)
28+ self .head : Node | None = None
29+ self .tail : Node | None = None
30+ # id -> node map to simulate pointer references
31+ # In a low-level language, we would just store/use the memory addresses.
32+ self ._nodes : dict [int , Node ] = {}
3033
34+ def _get_node (self , node_id : int ) -> Node | None :
35+ """Helper to retrieve a node by its simulated ID."""
36+ return self ._nodes .get (node_id )
3137
32- def _xor (self , a : Optional [Node ], b : Optional [Node ]) -> int :
33- return (id (a ) if a else 0 ) ^ (id (b ) if b else 0 )
38+ def _get_id (self , node : Node | None ) -> int :
39+ """Helper to get the simulated ID (address) of a node."""
40+ return id (node ) if node else 0
41+
42+ def _xor (self , a : Node | None , b : Node | None ) -> int :
43+ """Helper to XOR the IDs (addresses) of two nodes."""
44+ # Use 'Node | None' instead of 'Optional[Node]' (per ruff UP045)
45+ return self ._get_id (a ) ^ self ._get_id (b )
3446
3547 def insert (self , value : int ) -> None :
48+ """Inserts a value at the end of the list."""
3649 node = Node (value )
50+ # Store the node in our simulated memory
3751 self ._nodes [id (node )] = node
52+
3853 if self .head is None :
39- self .head = self .tail = node
54+ # List is empty
55+ self .head = node
56+ self .tail = node
57+ # node.both remains 0 (XOR of None and None)
4058 else :
41- node .both = id (self .tail )
42- self .tail .both ^= id (node )
59+ # List is not empty, append to tail
60+ # New node's 'both' points back to the old tail
61+ node .both = self ._get_id (self .tail )
62+
63+ # Update the old tail's 'both'
64+ # old_tail.both = (ID of node before old_tail) ^ (ID of new node)
65+ # We can get (ID of node before old_tail) by doing:
66+ # old_tail.both ^ (ID of next node, which was None/0)
67+ # So, old_tail.both ^ 0 = old_tail.both
68+ # new_tail.both = old_tail.both ^ self._get_id(node)
69+
70+ # Simplified:
71+ # self.tail.both was (ID of prev_node) ^ 0
72+ # We need it to be (ID of prev_node) ^ (ID of new node)
73+ # So we XOR it with the new node's ID.
74+ if self .tail : # Type checker guard
75+ self .tail .both = self .tail .both ^ self ._get_id (node )
76+
77+ # Update the tail pointer
4378 self .tail = node
4479
4580 def to_list (self ) -> list [int ]:
81+ """Converts the XOR linked list to a standard Python list (forward)."""
4682 result = []
47- prev_id = 0
4883 current = self .head
84+ prev_id = 0 # ID of the virtual 'None' node before head
85+
4986 while current :
5087 result .append (current .value )
88+
89+ # Get the ID of the next node
90+ # current.both = (ID of prev_node) ^ (ID of next_node)
91+ # So, (ID of next_node) = (ID of prev_node) ^ current.both
5192 next_id = prev_id ^ current .both
52- prev_id = id (current )
53- current = self ._nodes .get (next_id )
93+
94+ # Move to the next node
95+ prev_id = self ._get_id (current )
96+ current = self ._get_node (next_id )
97+
5498 return result
5599
56100
57101if __name__ == "__main__" :
58102 import doctest
103+
59104 doctest .testmod ()
105+
106+ # Additional demonstration
107+ xor_list = XORLinkedList ()
108+ xor_list .insert (10 )
109+ xor_list .insert (20 )
110+ xor_list .insert (30 )
111+ print (f"List contents: { xor_list .to_list ()} " ) # Output: [10, 20, 30]
112+
113+ # Verify head and tail
114+ if xor_list .head :
115+ print (f"Head value: { xor_list .head .value } " ) # Output: 10
116+ if xor_list .tail :
117+ print (f"Tail value: { xor_list .tail .value } " ) # Output: 30
0 commit comments