算法导论 XOR双向循环链表——内存高效链表

本文介绍了如何仅使用一个指针值x.np实现内存高效的XOR双向循环链表,详细阐述了算法导论中关于此问题的原题,以及如何在O(1)时间内完成链表的搜索、插入、删除和反转操作。通过C++代码展示了具体实现,并给出了程序运行结果。

XOR双向循环链表——内存高效链表

1. 算法导论原题

10.2-8 ★(★代表题目略有难度)
Explain how to implement doubly linked lists using only one pointer value x.np per item instead of the usual two(next and pre). Assume that all pointer values can be interpreted as k-bit integers, and define x.np to be x.np = x.next XOR x.pre,the k-bit“exclusive-or” of x.next and x.pre.(The value NIL is represented by 0.) Be sure to describe what information you need to access the head of the list. Show how to implement the SEARCH, INSERT, and DELETE operations on such a list. Also show how to reverse such a list in O(1) time.
译:解释如何在每个结点里不用两个指针(next指针和pre指针),而是只使用一个指针x.np实现双链表(译者注:x指结点对象)。假设所有指针指都是k位二进制的整数,并且定义x.np为x.next XOR x.pre(即x.next和x.pre的k位按位异或)。确保描述你需要进入链表第一个结点的所有信息。展示在这样一个链表如何实现搜索、插入和删除操作。同时展示如何在O(1)的时间复杂度内反转链表。

2. XOR双向循环链表如何实现?

跟普通双向链表不同的是,指向前结点的指针pre和指向后结点的指针next都按位异或成一个指针np。
1. 第一个问题,如何通过这一个指针np来遍历链表呢?
按位异或有这样一个功能:已知A^B=C,那么有C^A=B,C^B=A。(注意的是顺序不影响按位异或的结果,A^B等价于B^A)(若不能理解按位异或的功能请看更详细的参考博文[1]《深入理解按位异或运算符》)。那么同理已知prev^next=NP,那么next^NP=preprev^NP=next。也就是说假设这里有链表已知两个结点A,B(且A的下一个结点就是B),那么要得到B的下一个结点C,只需要将结点A的地址(B.pre)和B.NP进行按位异或,就得到结点C的地址(B.next)。同理要得到结点A的前一个结点(A.pre),只需要将A.NP和结点B的地址(A.next)进行按位异或即可。(若不能理解这一点,请看更详细的参考博文[2]《XOR Linked List – A Memory Efficient Doubly Linked List》)。
2. 第二个问题,如何得到链表第一个结点?
因为要两个结点才能访问下一个结点,所以我们将链表定义为两个结点的结合(头结点和尾结点),而不是原来只有一个头节点。这样每次循环都可以通过当前两个结点来访问到下一个结点。
3. 第三个问题,如何在O(1)时间内反转链表?
因为在开始遍历的时候,我们将尾结点的地址和头结点的NP按位异或得到头节点的下一个结点。我们知道只要通过两个结点就可以访问上一个或下一个结点(即头节点的地址和尾结点的NP按位异或得到尾结点的上一个结点),那么只要我们将头节点和尾结点交换,是可以反转这个遍历的顺序的:这个时候尾结点的地址就是原来头节点的地址,头结点的NP就是原来尾结点的NP,所以链表会按照从原来头节点到原来尾结点的顺序进行遍历。

3. C++ 实现

//XORCircularDoubleLink.h
#pragma once

#include <assert.h>
#include <stdio.h>
#include "Util.h"

template<typename ElemType>
class Node
{
public:
    Node(ElemType* pData = NULL, Node<ElemType>* pNext = NULL, Node<ElemType>* pPrev = NULL);
    ElemType* const& GetData() const;
    void SetData(ElemType* val);
    ElemType* HavaData();
    Node<ElemType>* GetNext(Node<ElemType>* prevNode) const;
    Node<ElemType>* GetPrev(Node<ElemType>* nextNode) const;
    Node<ElemType>* const& GetNP() const ;
    void SetNP(Node<ElemType>* prevNode, Node<ElemType>* nextNode);
private:
    ElemType* m_pData;
    Node<ElemType>* m_pNP;
};


template<typename ElemType>
class XORCircularDoubleLink
{
public:
    XORCircularDoubleLink();
    unsigned int const& GetLength() const;
    bool Insert(ElemType elem, unsigned int pos);
    bool Delete(unsigned int pos, ElemType* elem);
    bool Search(
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值