您的位置:首页 > 编程语言 > C语言/C++

C++使用单指针Struct实现双向链表

2017-07-07 15:13 302 查看
数学基础

离散数学中的异或运算 a⊕b,具有以下性质

a⊕b = b⊕a

a⊕a = 0

a⊕0 = a

a⊕(a⊕b) = (a⊕a)⊕b = b

(a⊕b)⊕b = a⊕(b⊕b) = a

单指针双向链表逻辑结构

单指针双向链表则需要采用异或链表的方式,下图是一个具有五个节点的双向链表的逻辑结构示意图,没有头结点。



其中每个节点的后半部分表示指针域,存储了它的前驱节点的指针与后继借点的指针的异或值。我们从最左边的节点开始遍历,就可以使用 0 ^ (0^P1) = P1 来得到下一个节点的指针(请注意,此处 0^P1 是一个整体,直接从节点的指针域中获得的)。继续往右走,又可以使用 P0 ^ (P0^P3) 来得到 P3,并以此类推。从右节点开始遍历也是同理(如:(P4^0) ^ 0 = P4)。

因此,按照上面的数据结构,就可以只使用一个指针域来实现双向链表了。

示例代码

#include <iostream>

using namespace std;

struct Node {
int num;
uintptr_t ptr;
};

void main() {
Node * head = NULL;
Node * tail = NULL;
Node * pre = NULL; //当前节点的前一个节点
Node * prepre = NULL;//当前节点前一个节点的前一个节点
int startNum = 1;
int nodeCount = 4;
// 创建新链表并填充内容
for(int i =0;i <nodeCount;i++) {
Node* node = new Node();
//从1开始编号
node->num = startNum++;
node->ptr = NULL;
if(head == NULL)  {
head = node;
pre = node;
}
else {
//实现双向链表
//创建新的节点时,计算前一个节点的ptr pre->ptr = node ^ prepre
pre->ptr = (uintptr_t)prepre ^ (uintptr_t)node;
//整体后移一个节点
prepre = pre;
pre = node;
tail = node;
}
}
tail->ptr = (uintptr_t)prepre ^ (uintptr_t)NULL;

//正向遍历
//最后一个元素为tail
cout<<"正向"<<endl;
pre = NULL;
Node* current = head;
while (current != NULL && current != tail)
{
cout<<current->num <<"\t";
Node* temp = (Node*)(current->ptr ^ (uintptr_t)pre);
pre = current;
current = temp;
}
cout<<tail->num <<"\n";

//反向遍历
//最后一个元素为head
cout<<"反向"<<endl;
pre = NULL;
current = tail;
while (current != NULL && current != head)
{
cout<<current->num <<"\t";
Node* temp = (Node*)(current->ptr ^ (uintptr_t)pre);
pre = current;
current = temp;
}
cout<<head->num <<"\n";

getchar();

}


最终输出为

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  指针 链表 c语言