異或連結串列 – 一種記憶體高效的雙向連結串列
連結串列
連結串列是一種線性資料結構,包含稱為節點的元素。每個節點包含兩個主要組成部分:資料(該節點的有效負載)和指向列表中下一個節點的指標。它們簡單易用,高效,易於分配和釋放記憶體。
雙向連結串列
雙向連結串列是一種特殊的連結串列,同樣由稱為節點的基本元素組成。每個節點包含三個主要組成部分:資料(該節點的有效負載)、指向序列中前一個節點的指標和指向序列中下一個節點的指標。這種雙向連結允許高效地雙向遍歷。
異或連結串列
異或連結串列,也稱為 XOR 雙向連結串列,使用按位異或 (^) 運算來節省記憶體,與傳統的雙向連結串列相比。每個節點包含兩個主要組成部分:資料(該節點的有效負載)以及序列中前一個節點和下一個節點的記憶體地址的異或值。
示例
給定一個雙向連結串列:A - B - C - D
異或表示為:
link(A) = NULL ^ address(B) link(B) = address(A) ^ address(C) link(C) = address(B) ^ address(D) link(D) = address(C) ^ NULL
正向遍歷
對於上面的示例,讓我們考慮正向遍歷,即從左到右,看看如何使用節點中儲存的連結到達下一個節點。給定正向遍歷,前一個節點的地址儲存在一個變數中。假設我們位於節點 B 並想要到達節點 C。
address(A) ^ link(B) = address(A) ^ (address (A) ^ address(C)) = 0 ^ address(C) = address(C)
反向遍歷
對於上面的示例,讓我們考慮反向遍歷,即從右到左,看看如何使用節點中儲存的連結到達下一個節點。給定反向遍歷,前一個節點的地址儲存在一個變數中。假設我們位於節點 D 並想要到達節點 C。
NULL ^ link(D) = NULL ^ (address(C) ^ NULL) = 0 ^ address(C) = address(C)
虛擬碼
structure Node: data : integer link : Node function xor(x : Node, y : Node) : Node return Node with address (address of x) xor (address of y) function traverse(head : Node) curr : Node = head prev : Node = null next : Node while curr is not null output curr.data, " --> " next = xor(prev, curr.link) prev = curr curr = next end while output "nullptr" function push(headRef : Node reference, data : integer) newNode : Node = create new Node newNode.data = data newNode.link = xor(headRef, null) if headRef is not null headRef.link = xor(newNode, xor(headRef.link, null)) end if headRef = newNode
示例:C++ 實現
#include <iostream> #include <vector> #include <cstdint> using namespace std; // Structure of XOR Linked list struct Node { int data; Node *link; }; // Dunction to calculate XOR of two node address Node *XOR(Node *x, Node *y) { return (Node *)((uintptr_t)(x) ^ (uintptr_t)(y)); } // Forward traversal void traverse(Node *head) { Node *curr = head; Node *prev = nullptr; Node *next; while (curr != nullptr) { cout << curr->data << " --> "; next = XOR(prev, curr->link); prev = curr; curr = next; } cout << "nullptr"; } // Function to push an element at front of XOR linked list void push(Node *&headRef, int data) { Node *newNode = new Node(); newNode->data = data; newNode->link = XOR(headRef, nullptr); if (headRef) { headRef->link = XOR(newNode, XOR(headRef->link, nullptr)); } headRef = newNode; } int main() { vector<int> values = {1, 2, 3, 4}; Node *head = nullptr; for (int i = values.size() - 1; i >= 0; i--) { push(head, values[i]); } traverse(head); return 0; }
輸出
1 --> 2 --> 3 --> 4 --> nullptr
結論
總之,異或連結串列是實現雙向連結串列的一種高效方法。但是它有點複雜,與雙向連結串列相比編碼不太容易,而且節點刪除也不可能。此外,許多語言(如 Java)不支援異或連結串列。
廣告