Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何实现只有一个指针的双链表?_Algorithm_Data Structures - Fatal编程技术网

Algorithm 如何实现只有一个指针的双链表?

Algorithm 如何实现只有一个指针的双链表?,algorithm,data-structures,Algorithm,Data Structures,如何实现只有一个指针的双链表 查找上一个和下一个节点需要O(1)个时间 struct Node { int val; Node* p; }; 这听起来好像是不可能的,就像它所说的那样。一般来说,不能只使用一个指针实现两个指针 您可能能够将两个16位偏移量压缩到单个(假定为32位)指针或其他一些“聪明的黑客”使用的空间中,但通常这听起来是不可能的 描述基于XOR的一个技巧:ING指针值,但我会考虑一个HACK(它对指针值进行位运算)。< P>也许使用一个.< /P> < P>如果 s

如何实现只有一个指针的双链表

查找上一个和下一个节点需要O(1)个时间

struct Node
{
   int val;
   Node* p;
};

这听起来好像是不可能的,就像它所说的那样。一般来说,不能只使用一个指针实现两个指针

您可能能够将两个16位偏移量压缩到单个(假定为32位)指针或其他一些“聪明的黑客”使用的空间中,但通常这听起来是不可能的

描述基于XOR的一个技巧:ING指针值,但我会考虑一个HACK(它对指针值进行位运算)。

< P>也许使用一个.< /P> < P>如果<代码> siZeof(int)= sisiof(节点*)< /代码>,则有一个中间节点,包含一个后指针。< /P> 例如

(实节点)->(中间节点)->(读节点)->(等)

其中
(实节点)
包含一个值和一个指向以下
(中间节点)
的指针,
(中间节点)
在val中包含指向前一个中间节点的后向指针,在p中包含指向以下
(读取节点)
的前向指针


顺便说一句,这是一个愚蠢的问题。我看不出它能教什么有价值的东西。

有一个经典的技巧:存储两个指针(上一个和下一个)的异或,当遍历列表时,你总是手头有一个指针(你刚从那里来),你可以将它与存储的值异或,以获得另一个指针


不用说,这在GC环境中不起作用。

已经提出的一个解决方案是

另一种解决方案是“翻转侧面”解决方案: 如果您的问题用以下方式表述:

将为您提供指向第一个元素的指针,您希望:

  • 在链表中前进i步骤O(i)
  • 在链接列表中返回i O(i)中的步骤
  • 在O(1)处的当前位置添加或删除项目
  • 因此,始终只有一个指向链表的指针,并且只有一个入口点(就像在1和2中一样,只是来回移动),您可以执行以下操作:

    • 保存两个指针:p1p2
    • 从第一个指针p1可以返回,从第二个指针p2可以前进
    • p1之前的链表项指向后,而p2之后的链表项指向前
    因此,您的列表如下所示:

                      p1 p2
                      |  |
                      V  V
    i1 <- i2 <- i3 <- i4 i5 -> i6 -> i7
    
    p1p2
    |  |
    V V
    
    i1我最近在Niklaus Wirth的一本书(“算法+数据结构=程序”)中偶然发现了解决这个问题的好方法。事情是这样的。。。您有一个节点,与您建议的节点类似,只是它不聚合指向下一个(或上一个)
    节点的指针。相反,您有一个成员
    链接
    ,它表示从链中的上一个节点(由
    节点*pPrev
    指向)到链中的下一个节点(由
    节点*pNext
    指向)的距离(例如,以
    大小为单位):

    size_t link = pNext - pPrev;
    
    因此,节点可能看起来像这样:

    struct Node {
        int val;
        size_t link;
    }
    
    然后,要从当前节点、
    pccurrent
    与上一个节点
    pPrev
    结合,通过写入以下内容,继续到下一个
    节点*pNext

    pNext = pPrev + pCurrent->link;
    
    类似地,通过重新排列此方程式,可以沿相反方向进行遍历:

    pPrev = pNext - pCurrent->link;
    

    然而,这种方法在某种程度上受到C/C++指针算法的限制,因为只有当两个指针都位于同一内存块内时,两个指针的差异才能得到很好的定义。因此,本质上,所有节点都必须包含在一个庞大的
    节点数组中。

    将列表限制为最多两个节点:p双向链接列表?你的意思是,如果有一个指向其任何节点的外部指针,就应该能够以两种方式遍历它?这个有趣的问题也出现在《编程Perls》第9节(第9列)中。虽然XOR基本解决方案经常被提出(可能是因为在那个时代,指针算法非常普遍),但我发现下面由“Anna”给出的解决方案非常有趣,尤其是当指针算法不可行时。“XOR”技巧几乎是我所知的唯一实现这一点的方法。如果您正在使用的系统内存有限,每个节点保存一个指针是值得的,那么它有一些合法的用途。不过,调试列表代码很有趣。鉴于这是一个面试问题,而不是一个实际问题,我大约99%确定它是作为一个一般知识问题。面试官想知道被面试者是否知道XOR技巧。
    pPrev = pNext - pCurrent->link;