📜  XOR链表–具有内存效率的双链表|套装2

📅  最后修改于: 2021-04-17 12:23:19             🧑  作者: Mango

在上一篇文章中,我们讨论了如何在每个节点的地址字段中仅使用一个空格来创建双向链接。在这篇文章中,我们将讨论内存高效的双向链表的实现。我们将主要讨论以下两个简单功能。

  1. 在开始处插入新节点的函数。
  2. 向前遍历列表的函数。

在下面的代码中, insert()函数在开始处插入一个新节点。我们需要更改“链表”的头指针,这就是为什么要使用双指针的原因(请参阅此)。让我们首先再讨论上一篇文章中讨论过的几件事。我们将下一个节点和上一个节点的XOR与每个节点存储在一起,我们将其称为npx,这是每个节点唯一的地址成员。当我们在开始处插入新节点时,新节点的npx将始终为NULL与当前头的XOR。并且必须将当前磁头的npx更改为新节点与当前磁头旁边的节点的XOR。
printList()向前遍历列表。它从每个节点打印数据值。要遍历列表,我们需要在每个点都获得指向下一个节点的指针。我们可以通过跟踪当前节点和上一个节点来获取下一个节点的地址。如果对curr-> npx和prev进行XOR,我们将获得下一个节点的地址。

C++
/* C++ Implementation of Memory
efficient Doubly Linked List */
#include 
#include 
using namespace std;
 
// Node structure of a memory
// efficient doubly linked list
class Node
{
    public:
    int data;
    Node* npx; /* XOR of next and previous node */
};
 
/* returns XORed value of the node addresses */
Node* XOR (Node *a, Node *b)
{
    return reinterpret_cast(
      reinterpret_cast(a) ^
      reinterpret_cast(b));
}
 
/* Insert a node at the beginning of the
XORed linked list and makes the newly
inserted node as head */
void insert(Node **head_ref, int data)
{
    // Allocate memory for new node
    Node *new_node = new Node();
    new_node->data = data;
 
    /* Since new node is being inserted at the
    beginning, npx of new node will always be
    XOR of current head and NULL */
    new_node->npx = *head_ref;
 
    /* If linked list is not empty, then npx of
    current head node will be XOR of new node
    and node next to current head */
    if (*head_ref != NULL)
    {
        // *(head_ref)->npx is XOR of NULL and next.
        // So if we do XOR of it with NULL, we get next
        (*head_ref)->npx = XOR(new_node, (*head_ref)->npx);
    }
 
    // Change head
    *head_ref = new_node;
}
 
// prints contents of doubly linked
// list in forward direction
void printList (Node *head)
{
    Node *curr = head;
    Node *prev = NULL;
    Node *next;
 
    cout << "Following are the nodes of Linked List: \n";
 
    while (curr != NULL)
    {
        // print current node
        cout<data<<" ";
 
        // get address of next node: curr->npx is
        // next^prev, so curr->npx^prev will be
        // next^prev^prev which is next
        next = XOR (prev, curr->npx);
 
        // update prev and curr for next iteration
        prev = curr;
        curr = next;
    }
}
 
// Driver code
int main ()
{
    /* Create following Doubly Linked List
    head-->40<-->30<-->20<-->10 */
    Node *head = NULL;
    insert(&head, 10);
    insert(&head, 20);
    insert(&head, 30);
    insert(&head, 40);
 
    // print the created list
    printList (head);
 
    return (0);
}
 
// This code is contributed by rathbhupendra


C
/* C Implementation of Memory
   efficient Doubly Linked List */
#include 
#include 
#include 
 
// Node structure of a memory
// efficient doubly linked list
struct Node
{
    int data;
    struct Node* npx; /* XOR of next and previous node */
};
 
/* returns XORed value of the node addresses */
struct Node* XOR (struct Node *a, struct Node *b)
{
    return (struct Node*) ((uintptr_t) (a) ^ (uintptr_t) (b));
}
 
/* Insert a node at the beginning of the
   XORed linked list and makes the newly
   inserted node as head */
void insert(struct Node **head_ref, int data)
{
    // Allocate memory for new node
    struct Node *new_node = (struct Node *) malloc (sizeof (struct Node) );
    new_node->data = data;
 
    /* Since new node is being inserted at the
       beginning, npx of new node will always be
       XOR of current head and NULL */
    new_node->npx = *head_ref;
 
    /* If linked list is not empty, then npx of
       current head node will be XOR of new node
       and node next to current head */
    if (*head_ref != NULL)
    {
        // *(head_ref)->npx is XOR of NULL and next.
        // So if we do XOR of it with NULL, we get next
        (*head_ref)->npx = XOR(new_node, (*head_ref)->npx);
    }
 
    // Change head
    *head_ref = new_node;
}
 
// prints contents of doubly linked
// list in forward direction
void printList (struct Node *head)
{
    struct Node *curr = head;
    struct Node *prev = NULL;
    struct Node *next;
 
    printf ("Following are the nodes of Linked List: \n");
 
    while (curr != NULL)
    {
        // print current node
        printf ("%d ", curr->data);
 
        // get address of next node: curr->npx is
        // next^prev, so curr->npx^prev will be
        // next^prev^prev which is next
        next = XOR (prev, curr->npx);
 
        // update prev and curr for next iteration
        prev = curr;
        curr = next;
    }
}
 
// Driver program to test above functions
int main ()
{
    /* Create following Doubly Linked List
    head-->40<-->30<-->20<-->10 */
    struct Node *head = NULL;
    insert(&head, 10);
    insert(&head, 20);
    insert(&head, 30);
    insert(&head, 40);
 
    // print the created list
    printList (head);
 
    return (0);
}


Python3
# Python3 implementation of Memory
# efficient Doubly Linked List
 
# library for providing C
# compatible data types
import ctypes
 
# Node class for memory
# efficient doubly linked list
class Node:
     
    def __init__(self, data):
         
        self.data = data
         
        # XOR of next and previous node
        self.npx = 0 
 
class XorLinkedList:
     
    def __init__(self):
         
        self.head = None
        self.__nodes = []
         
    # Returns XORed value of the node addresses
    def XOR(self, a, b):
         
        return a ^ b
       
    # Insert a node at the beginning of the
    # XORed linked list and makes the newly
    # inserted node as head
    def insert(self, data):
         
        # New node
        node = Node(data)
 
        # Since new node is being inserted at
        # the beginning, npx of new node will
        # always be XOR of current head and NULL
        node.npx = id(self.head)
 
        # If linked list is not empty, then
        # npx of current head node will be
        # XOR of new node and node next to
        # current head
        if self.head is not None:
             
            # head.npx is XOR of None and next.
            # So if we do XOR of it with None,
            # we get next
            self.head.npx = self.XOR(id(node),
                                     self.head.npx)
 
        self.__nodes.append(node)
         
        # Change head
        self.head = node
 
    # Prints contents of doubly linked
    # list in forward direction
    def printList(self):
       
        if self.head != None:
            prev_id = 0
            curr = self.head
            next_id = 1
             
            print("Following are the nodes "
                  "of Linked List:")
             
            while curr is not None:
                 
                # Print current node
                print(curr.data, end = ' ')
                 
                # Get address of next node: curr.npx is
                # next^prev, so curr.npx^prev will be
                # next^prev^prev which is next
                next_id = self.XOR(prev_id, curr.npx)
                 
                # Update prev and curr for next iteration
                prev_id = id(curr)
                curr = self.__type_cast(next_id)
 
    # Method to return a new instance of type
    # which points to the same memory block.
    def __type_cast(self, id):
         
        return ctypes.cast(id, ctypes.py_object).value
 
# Driver code
if __name__ == '__main__':
     
    obj = XorLinkedList()
     
    # Create following Doubly Linked List
    # head-->40<-->30<-->20<-->10
    obj.insert(10)
    obj.insert(20)
    obj.insert(30)
    obj.insert(40)
 
    # Print the created list
    obj.printList()
 
# This code is contributed by MuskanKalra1


输出
Following are the nodes of Linked List: 
40 30 20 10