Algorithm 如何实现只有一个指针的双链表?
如何实现只有一个指针的双链表 查找上一个和下一个节点需要O(1)个时间Algorithm 如何实现只有一个指针的双链表?,algorithm,data-structures,Algorithm,Data Structures,如何实现只有一个指针的双链表 查找上一个和下一个节点需要O(1)个时间 struct Node { int val; Node* p; }; 这听起来好像是不可能的,就像它所说的那样。一般来说,不能只使用一个指针实现两个指针 您可能能够将两个16位偏移量压缩到单个(假定为32位)指针或其他一些“聪明的黑客”使用的空间中,但通常这听起来是不可能的 描述基于XOR的一个技巧:ING指针值,但我会考虑一个HACK(它对指针值进行位运算)。< P>也许使用一个.< /P> < P>如果 s
struct Node
{
int val;
Node* p;
};
这听起来好像是不可能的,就像它所说的那样。一般来说,不能只使用一个指针实现两个指针 您可能能够将两个16位偏移量压缩到单个(假定为32位)指针或其他一些“聪明的黑客”使用的空间中,但通常这听起来是不可能的
描述基于XOR的一个技巧:ING指针值,但我会考虑一个HACK(它对指针值进行位运算)。
< P>也许使用一个.< /P> < P>如果<代码> siZeof(int)= sisiof(节点*)< /代码>,则有一个中间节点,包含一个后指针。< /P> 例如(实节点)->(中间节点)->(读节点)->(等)
其中(实节点)
包含一个值和一个指向以下(中间节点)
的指针,(中间节点)
在val中包含指向前一个中间节点的后向指针,在p中包含指向以下(读取节点)
的前向指针
顺便说一句,这是一个愚蠢的问题。我看不出它能教什么有价值的东西。有一个经典的技巧:存储两个指针(上一个和下一个)的异或,当遍历列表时,你总是手头有一个指针(你刚从那里来),你可以将它与存储的值异或,以获得另一个指针
不用说,这在GC环境中不起作用。已经提出的一个解决方案是 另一种解决方案是“翻转侧面”解决方案: 如果您的问题用以下方式表述: 将为您提供指向第一个元素的指针,您希望:
- 保存两个指针:p1,p2
- 从第一个指针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;