数学基础
离散数学中的异或运算 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++使用单指针Struct实现双向链表
最新推荐文章于 2025-02-07 20:16:13 发布