[英]Why can't you build a xor linked list in python 3?
我想在 python 中實現一個異或鏈表,我搜索它以嘗試更好地理解它,但我發現的唯一與 python 相關的是這個 stackoverflow 帖子How to implement an XOR Linked List in ZA7F5F35426B9237411FC92311B? 這表示不可能在 python 中實現異或鏈表。 它在那里說你不能亂用位和指針。 我認為我們實際上可以“搞亂位”,使用按位運算符(對於 xor 我們會有 ^ ),指針是什么意思? 我們可以創建一個帶有指針屬性的節點 class ,就像我們在單鏈表中所做的那樣:
class Node(object):
def __init__(self, data):
self.data = data
self.next = None
那將是我們的帶有“指針”->.next 的節點。 那么,問題是,為什么我們不能在 python 中實現 XOR 鏈表,如果可以,怎么做?
我可以成功地實現一個 XOR 鏈表。 請注意,為了設置Node
的鄰居,您必須通過兩個鄰居。 如果您不這樣做,則無法使用 XOR 運算 ( address_store = prev_address ^ curr_address
) 計算地址。
get_by_address(address)
function 將在運行時為您提供具有給定id
的 object ,而Node.get_address(node)
將為您提供Node
的id
。 顯然,可以在 Python 中取消引用 object 並獲得它的引用!
def get_by_address(address, global_vars):
if address == 0:
return None
return [x for x in global_vars.values() if id(x) == address][0]
class Node(object):
def __init__(self, data):
self.data = data
self.address_store = None
def get_address(self):
return id(self)
def set_neighbors(self, prev_node=None, next_node=None):
local_address = self.get_address()
if prev_node == None:
prev_address = 0
else:
prev_address = prev_node.get_address()
if next_node == None:
next_address = 0
else:
next_address = next_node.get_address()
self.address_store = prev_address ^ next_address
def get_next(self, prev_node, global_vars):
if self.address_store == None:
raise Exception('set_neighbors not called yet, no next node!')
if prev_node == None:
prev_address = 0
else:
prev_address = prev_node.get_address()
next_address = self.address_store ^ prev_address
return get_by_address(address=next_address, global_vars=global_vars)
def get_prev(self, next_node, global_vars):
if self.address_store == None:
raise Exception('set_neighbors not called yet, no next node!')
if next_node == None:
next_address = 0
else:
next_address = next_node.get_address()
prev_address = self.address_store ^ next_address
return get_by_address(prev_address, global_vars=global_vars)
node1 = Node(data=1)
node2 = Node(data=2)
node3 = Node(data=3)
node1.set_neighbors(prev_node=None, next_node=node2)
node2.set_neighbors(prev_node=node1, next_node=node3)
node3.set_neighbors(prev_node=node2, next_node=None)
curr_node = node1
prev_node = None
print('Traversing forwards:')
print(str(None), '<->', end=' ')
while curr_node != None:
print(curr_node.data, '<->', end=' '),
prev_node_temp = curr_node
curr_node = curr_node.get_next(prev_node=prev_node, global_vars=globals())
prev_node = prev_node_temp
print(str(None))
curr_node = node3
prev_node = None
print('Traversing backwards:')
print(str(None), '<->', end=' ')
while curr_node != None:
print(curr_node.data, '<->', end=' '),
prev_node_temp = curr_node
curr_node = curr_node.get_next(prev_node=prev_node, global_vars=globals())
prev_node = prev_node_temp
print(str(None))
Output:
Traversing forwards:
None <-> 1 <-> 2 <-> 3 <-> None
Traversing backwards:
None <-> 3 <-> 2 <-> 1 <-> None
異或鏈表存儲兩個地址的異或以節省存儲空間。 這在直接操作 memory 地址的低級語言中很有用。 在 Python 中沒有那么多,因為在 Python 中,您沒有直接處理 memory。
Python 名稱(變量)是對由 Python 運行時管理的對象的引用。 但該引用不是 memory 地址。
在 CPython 中,您可以通過使用id()
function或多或少地獲取 object 的地址,但這是 CPython 的實現細節,而不是語言的屬性。 此外,Python 對象比您想象的要大得多。 在類 C 語言中,integer 通常是 4 個字節。
Python 為“高效的 arrays 數值數組”提供了array
。讓我們創建一個 4 字節整數數組;
In [5]: import array
In [6]: a = array.array('l', range(10))
Out[6]: array('l', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
讓我們看看數組中第一項和第二項的地址之間的差異:
In [7]: id(a[1]) - id(a[0])
Out[7]: 32
所以在我的機器上,一個4字節的integer作為CPython object的大小實際上是32字節。 這基本上是因為 Python 運行時必須在幕后做很多工作來為您管理 memory。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.