异或链表 – 一种内存高效的双向链表
链表
链表是一种线性数据结构,包含称为节点的元素。每个节点包含两个主要组成部分:数据(该节点的有效负载)和指向列表中下一个节点的指针。它们简单易用,高效,易于分配和释放内存。
双向链表
双向链表是一种特殊的链表,同样由称为节点的基本元素组成。每个节点包含三个主要组成部分:数据(该节点的有效负载)、指向序列中前一个节点的指针和指向序列中下一个节点的指针。这种双向链接允许高效地双向遍历。
异或链表
异或链表,也称为 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)不支持异或链表。
广告