簡體   English   中英

為什么不能在 python 3 中建立異或鏈表?

[英]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)將為您提供Nodeid 顯然,可以在 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM