Memory efficient linked list is also called XOR Linked List.
To use lesser memory in doubly link list, such data structure is used.
An ordinary doubly linked list stores addresses of the previous and next list items in each list node, requiring two address fields:
An XOR linked list compresses the same information into one address field by storing the bitwise XOR (here denoted by ⊕) of the address for previous and the address for next in one field:
We can traverse the XOR list in both forward and reverse direction. While traversing the list we need to remember the address of the previously accessed node in order to calculate the next node’s address
For example:
When we are at node C, we must have address of B stored in some extra variable.
XOR of ADD(B) and XAdd of C gives us the ADD(D).
Reason is simple: XAdd(C) is : “ADD(B) XOR ADD(D)”.
If we do xor of XAdd(C) with ADD(B), we get the result as
“ADD(B) XOR ADD(D) XOR ADD(B)” = “ADD(D) XOR 0″ = “ADD(D)”.
So we have the address of next node.
Similarly we can traverse the list in backward direction.
#include <stdio.h>
#include <stdlib.h>
#define gc getchar_unlocked
inline int scan(){register int n=0,c=gc();while(c<'0'||c>'9')c=gc();while(c<='9'&&c>='0')n=(n<<1)+(n<<3)+c-'0',c=gc();return n;}
typedef struct node
{
int data;
struct node* np; /* XOR of next and previous node */
}node;
node *head, *tail;
struct node* XOR (struct node *a, struct node *b){
return (struct node*) ((unsigned int) (a) ^ (unsigned int) (b));
}
void insert(int data)
{
node *new_node = (node*) malloc(sizeof(node));
new_node->data = data;
if (NULL == head) {
new_node->np = NULL;
head = tail = new_node;
}
//else if (at_tail) {
else{
new_node->np = XOR(tail, NULL);
tail->np = XOR(new_node, XOR(tail->np, NULL));
tail = new_node;
}
/*else { //code to enter new node at head
new_node->np = XOR(NULL, head);
head->np = XOR(new_node, XOR(NULL, head->np));
head = new_node;
}*/
}
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){
printf ("%d ", curr->data);
next = XOR (prev, curr->np);
prev = curr;
curr = next;
}
}
// Driver program to test above functions
int main ()
{
//struct node *head = (struct node *) malloc (sizeof (struct node) );
head = NULL;
int t,n;
t=scan();
printf("%d\n",t);
while(t--){
n=scan();
insert(n);
}
printList (head);
return (0);
}
See working code at http://ideone.com/YdZmJk
Reference : http://www.linuxjournal.com/
To use lesser memory in doubly link list, such data structure is used.
An ordinary doubly linked list stores addresses of the previous and next list items in each list node, requiring two address fields:
... A B C D E ... –> next –> next –> next –> <– prev <– prev <– prev <–
An XOR linked list compresses the same information into one address field by storing the bitwise XOR (here denoted by ⊕) of the address for previous and the address for next in one field:
... A B C D E ... <–> A⊕C <-> B⊕D <-> C⊕E <->
We can traverse the XOR list in both forward and reverse direction. While traversing the list we need to remember the address of the previously accessed node in order to calculate the next node’s address
For example:
When we are at node C, we must have address of B stored in some extra variable.
XOR of ADD(B) and XAdd of C gives us the ADD(D).
Reason is simple: XAdd(C) is : “ADD(B) XOR ADD(D)”.
If we do xor of XAdd(C) with ADD(B), we get the result as
“ADD(B) XOR ADD(D) XOR ADD(B)” = “ADD(D) XOR 0″ = “ADD(D)”.
So we have the address of next node.
Similarly we can traverse the list in backward direction.
#include <stdio.h>
#include <stdlib.h>
#define gc getchar_unlocked
inline int scan(){register int n=0,c=gc();while(c<'0'||c>'9')c=gc();while(c<='9'&&c>='0')n=(n<<1)+(n<<3)+c-'0',c=gc();return n;}
typedef struct node
{
int data;
struct node* np; /* XOR of next and previous node */
}node;
node *head, *tail;
struct node* XOR (struct node *a, struct node *b){
return (struct node*) ((unsigned int) (a) ^ (unsigned int) (b));
}
void insert(int data)
{
node *new_node = (node*) malloc(sizeof(node));
new_node->data = data;
if (NULL == head) {
new_node->np = NULL;
head = tail = new_node;
}
//else if (at_tail) {
else{
new_node->np = XOR(tail, NULL);
tail->np = XOR(new_node, XOR(tail->np, NULL));
tail = new_node;
}
/*else { //code to enter new node at head
new_node->np = XOR(NULL, head);
head->np = XOR(new_node, XOR(NULL, head->np));
head = new_node;
}*/
}
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){
printf ("%d ", curr->data);
next = XOR (prev, curr->np);
prev = curr;
curr = next;
}
}
// Driver program to test above functions
int main ()
{
//struct node *head = (struct node *) malloc (sizeof (struct node) );
head = NULL;
int t,n;
t=scan();
printf("%d\n",t);
while(t--){
n=scan();
insert(n);
}
printList (head);
return (0);
}
See working code at http://ideone.com/YdZmJk
Reference : http://www.linuxjournal.com/