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

  1. 数学基础

    离散数学中的异或运算 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
  2. 单指针双向链表逻辑结构

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

    这里写图片描述

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

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

  3. 示例代码

    
    #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();
    
    
    }

    最终输出为
    这里写图片描述

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值