异或链表(XOR linked list)
异或链表(Xor Linked List)也是一种链式存储结构,它可以降低空间复杂度达到和双向链表一样目的,任何一个节点可以方便的访问它的前驱节点和后继结点。可以参阅wiki
普通的双向链表
class Node {
public:
int data;
Node *prev;
Node *next;
};
class BiLinkedList {
public:
Node *head;
Node *tail;
};
普通双向链表的一个节点表示如下:
完整的普通双向链表如下所示:
对于异或链表来说,只是用一个xorPtr指针取代prev和next两个指针,这对于空间效率是一个提升。
template<typename ElemType>
class XorNode {
public:
ElemType data;
XorNode<ElemType> *xorPtr;
XorNode(ElemType data):data(data) { }
}; template<typename ElemType>
class XorLinkedList {
public:
XorNode<ElemType> *head;
XorNode<ElemType> *tail;
}
异或链表如下图所示,每一个Node记录data数据和xorPtr异或指针,异或指针记录前后两个指针的地址值的异或值

B的异或指针如下构造
B->xorPtr = addr(A) ⊕ addr(C)
获取B的前驱A的地址
addr(A) = B->xorPtr ⊕ addr(C)
获取B的后继C的地址
addr(C) = B->xorPtr ⊕ addr(A)
通过以上的几种操作,就可以遍历整个链表,在处理添加、插入、删除等操作时同普通的双向链表类似,在纸上多画画之间的关系就OK。
记得处理边界,比如只剩一个节点进行删除操作时候,要判断前继和后驱Node是否为NULL,操作前要进行链表是否为空和越界的判断,xor是关键字。
另外,B的xorPtr也可以类似的使用加法运算A+C, 假设B的指针是ptr,B的前驱为B->ptr – C, B的后继为B->ptr-A。
指针转换为无符号整形,然后进行异或操作。
这些异或和加法相关的操作都是针对指针值的本身,即指针转换为无符号整型数的结构,不能跟指针的运算操作混淆。
下面就是完整的代码。
#include <bits/stdc++.h>
using namespace std;
#define ERROR -1 // XorNode Class
template<typename ElemType>
class XorNode {
public:
ElemType data;
XorNode<ElemType> *xorPtr;
XorNode(ElemType data):data(data) { }
}; // XorLinkedList Class
template<typename ElemType>
class XorLinkedList {
public:
XorNode<ElemType> *head;
XorNode<ElemType> *tail;
int size; // constructor function
XorLinkedList() {
head = NULL;
tail = NULL;
size = 0;
} // is xorlinkedlist empty
bool isEmpty() {
return head == NULL && tail == NULL;
} // xorlinkedlist length
int length() {
return size;
} // add element into back
void addBack(ElemType e) {
XorNode<ElemType> *newNode = new XorNode<ElemType>(e);
if (isEmpty()) {
newNode->xorPtr = xor_func(NULL, NULL);
head = newNode;
tail = newNode;
} else {
newNode->xorPtr = xor_func(tail, NULL);
tail->xorPtr = xor_func(xor_func(tail->xorPtr, NULL), newNode);
tail = newNode;
}
size++;
} //add element into front
void addFront(ElemType e) {
XorNode<ElemType> *newNode = new XorNode<ElemType>(e);
if (isEmpty()) {
newNode->xorPtr = xor_func(NULL, NULL);
head = newNode;
tail = newNode;
} else {
newNode->xorPtr = xor_func(NULL, head);
head->xorPtr = xor_func(newNode, xor_func(head->xorPtr, NULL));
head = newNode;
}
size++;
} // pop element from back
ElemType popBack() {
if (isEmpty()) {
cout << "XorLinkedList is empty." << endl;
return ERROR;
}
XorNode<ElemType> *tmpNode = tail;
ElemType ret = tail->data; tail = xor_func(tail->xorPtr, NULL);
if (tail) tail->xorPtr = xor_func(xor_func(tail->xorPtr, tmpNode), NULL);
else head = NULL;
delete[] tmpNode;
size--;
return ret;
} // pop element from front
ElemType popFront() {
if (isEmpty()) {
cout << "XorLinkedList is empty." << endl;
return ERROR;
}
XorNode<ElemType> *tmpNode = head;
ElemType ret = head->data;
head = xor_func(NULL, head->xorPtr);
// if not pop last node, set the xorPtr
if (head) head->xorPtr = xor_func(NULL, xor_func(head->xorPtr, tmpNode));
else tail = NULL;
delete[] tmpNode;
size--;
return ret;
} // return the value of pos
ElemType getValue(int pos) {
if (pos < 0 || pos >= length()) {
cout << "pos ranges from " << 0 << " to " << length() - 1 << endl;
return ERROR;
}
int step = 0;
XorNode<ElemType> *curNode = NULL;
if (pos <= length()/2) {
curNode = head;
step = pos;
} else {
curNode = tail;
step = length() - pos - 1;
}
int i = 0;
XorNode<ElemType> *otherNode = NULL, *tmpNode = NULL;
while (i < step && curNode != NULL) {
tmpNode = curNode;
curNode = xor_func(curNode->xorPtr, otherNode);
otherNode = tmpNode;
i++;
}
return curNode->data;
} // insert a node before pos
void insert(ElemType e, int pos) {
if (pos < 0 || pos > length()) {
cout << "pos ranges from " << 0 << " to " << length() << endl;
cout << "0: add element in front, " << length() << ": add element in back." << endl;
return;
}
// deal with front and back
if (pos == 0) addFront(e);
else if(pos == length()) addBack(e);
else {
XorNode<ElemType> *curNode = NULL, *tmpNode = NULL, *otherNode = NULL;
int i = 0;
curNode = head;
// find the pos
while (i < pos && curNode != NULL) {
tmpNode = curNode;
curNode = xor_func(curNode->xorPtr, otherNode);
otherNode = tmpNode;
i++;
}
// insert the newNode before pos
XorNode<ElemType> *newNode = new XorNode<ElemType>(e);
newNode->xorPtr = xor_func(curNode, otherNode);
otherNode->xorPtr = xor_func(xor_func(otherNode->xorPtr, curNode), newNode);
curNode->xorPtr = xor_func(newNode, xor_func(otherNode, curNode->xorPtr));
size++;
}
} // delete the element at pos
void remove(int pos) {
if (isEmpty()) {
cout << "XorLinkedList is empty" << endl;
return;
}
if (pos < 0 || pos >= length()) {
cout << "pos ranges from " << 0 << " to " << length()-1 << endl;
return;
}
if (pos == 0) popFront();
else if (pos == length()) popBack();
else {
int step = 0;
XorNode<ElemType> *curNode = NULL;
if (pos <= length()/2) {
curNode = head;
step = pos;
} else {
curNode = tail;
step = length() - pos - 1;
}
int i = 0;
XorNode<ElemType> *otherNode = NULL, *tmpNode = NULL, *nextNode = NULL;
while (i < step && curNode != NULL) {
tmpNode = curNode;
curNode = xor_func(curNode->xorPtr, otherNode);
otherNode = tmpNode;
i++;
}
nextNode = xor_func(curNode->xorPtr, otherNode);
if (otherNode) otherNode->xorPtr = xor_func(xor_func(otherNode->xorPtr, curNode), nextNode);
if (nextNode) nextNode->xorPtr = xor_func(otherNode, xor_func(nextNode->xorPtr, curNode));
delete[] curNode;
size--;
} } // traverse the xorlinkedlist.
// f: head -> tail
// r: tail -> head
void traverse(char direction = 'f') {
if (isEmpty()) {
cout << "XorLinkedList is empty" << endl;
return;
} if (direction != 'f' && direction != 'r') {
cout << "direction error, 'f' or 'r'." << endl;
return;
} XorNode<ElemType> *curNode = NULL, *otherNode = NULL, *tmpNode = NULL;
if (direction == 'f') curNode = head; // head -> tail
else if (direction == 'r') curNode = tail; // tail -> head
do {
cout << curNode->data << " ";
tmpNode = curNode;
curNode = xor_func(curNode->xorPtr, otherNode);
otherNode = tmpNode;
} while (curNode != NULL);
cout << endl;
} private:
XorNode<ElemType>* xor_func(XorNode<ElemType> *a, XorNode<ElemType> *b) {
return (XorNode<ElemType>*)((unsigned long)(a) ^ (unsigned long)(b));
}
}; int main() {
XorLinkedList<int> xll;
xll.insert(1,0);
xll.insert(2,1);
xll.insert(3,1);
xll.traverse('f');
// for (int i = 0; i < 3; i++)
// cout << xll.popBack() << endl;
xll.remove(1);
xll.traverse('f');
cout << endl;
return 0;
}
异或链表(XOR linked list)的更多相关文章
- XOR linked list--- 异或链表
异或链表的结构 这是一个数据结构.利用计算机的的位异或操作(⊕),来降低双向链表的存储需求. ... A B C D E ... –> next –> next –> next –& ...
- 【机器学习】神经网络实现异或(XOR)
注:在吴恩达老师讲的[机器学习]课程中,最开始介绍神经网络的应用时就介绍了含有一个隐藏层的神经网络可以解决异或问题,而这是单层神经网络(也叫感知机)做不到了,当时就觉得非常神奇,之后就一直打算自己实现 ...
- 【ShareCode】不错的技术文章 -- 如何使用异或(XOR)运算找到数组中缺失的数?
如何使用异或(XOR)运算找到数组中缺失的数? 今天给大家分享一篇关于使用XOR(异或)运算找到数组中缺失的数的问题. 在一次Javascript面试中,有这么一个问题: 假设有一个由0到99(包含9 ...
- LeetCode 234:回文链表 Palindrome Linked List
请判断一个链表是否为回文链表. Given a singly linked list, determine if it is a palindrome. 示例 1: 输入: 1->2 输出: ...
- 链表(Linked List)
链表(Linked List) 一.介绍 链表是有序的列表,它在内存中存储方式(物理存储)如下: 小结: (1)链表是以节点的方式来存储,是链式存储. (2)每个节点包含 data 域:存储数据:ne ...
- 【数据结构与算法】——链表(Linked List)
链表(Linked List)介绍 链表是有序的列表,但是它在内存中是存储如下: 链表是以节点的方式来存储的,是链式存储. 每个节点包含data域,next域:指向下一个节点. 如图:链表的各个节点不 ...
- 关于异或(Xor)的一点笔记
因为博弈论里,尤其实在求sg函数时,经常会用到异或运算,所以我就把网上搜到的一些相关知识和自己的一些理解记下来. 如果出现差错,还请指出,谢谢! 异或:可以简称Xor,可以用数学符号⊕表示,计算机就一 ...
- LeetCode之“链表”:Linked List Cycle && Linked List Cycle II
1.Linked List Cycle 题目链接 题目要求: Given a linked list, determine if it has a cycle in it. Follow up: Ca ...
- [Swift]LeetCode142. 环形链表 II | Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Note ...
随机推荐
- modelsim仿真xilinx mig ip core相关问题
1.运用自动化脚本文件 do sim.do 其中不支持 .f文件 , 需要直接vlog 2.对于mig模型采用下面句型(根据example中do sim.do文件) vlog -sv +define ...
- GoogleNet tips
Inception Module googlenet的Inception Module Idea 1: Use 1x1, 3x3, and 5x5 convolutions in parallel t ...
- python实验二:字符串排序
##统计word中的各个字符的出现的次数,并统计出所有前十名的字符使用次数 # -*- coding:utf-8 -*- word='''awfesdafhjkcasadckjsdackjsadvcn ...
- EF 连接MySQL 数据库 保存中文数据后乱码问题
EF 连接MySQL 数据库 保存中文数据后乱码问题 采用Code First 生成的数据库,MySQL数据库中,生成的表的编码格式为***** 发现这个问题后,全部手动改成UTF8(图是另一个表的 ...
- [转] Oracle analyze table 使用总结
转自:http://www.cnblogs.com/einyboy/archive/2012/08/09/2630321.html analyze table 一般可以指定分析: 表,所有字段,所有索 ...
- VS2010+C#+AutoCAD2008时断点调试功能无效的处理方法
把acad.exe.config文件修改为:------------------------------------------------------------------------------ ...
- js操作document文档元素 节点交换交换
<input type="text" value="1" id='text1'> <input type="text" v ...
- PowerShell全自动分配CPU
代码 $pro = Get-Process foreach ($n in $pro){ if($n.ProcessorAffinity -ne 255){ #continue } if($n.Id - ...
- controller错误统一处理--------@ExceptionHandler
用@RequestBody,@ResponseBody,不费吹灰之力就解决了JSon自动绑定.接着就发现,如果遇到RuntimeException,需要给出一个默认返回JSON 三种方式: 1.当这个 ...
- Linux 流程控制语句 if else、for、while、until
1. 单分支if条件语句 书写方式1: if [ 条件判断式 ]; then 执行程序代码 fi 书写方式2: if [ 条件判断式 ] then 执行程序代码 fi 举例: if [ $rate - ...

