Python 单链表删除

Python 单链表删除,python,c,linked-list,singly-linked-list,Python,C,Linked List,Singly Linked List,我当时在做单链表实现,我记得Linus Torvalds谈到过它 在单链表中,为了删除节点,我们应该可以访问上一个节点,然后更改它当前指向的节点 像这样 因此,无论如何,我们都应该可以访问上一个节点 但是Linus Torvalds通过在C中使用地址的概念删除了这个特例。因此head也有“前面的东西”,即指向head的head的地址。因此,他使用了C的指针和地址特性来删除特殊情况 带特殊情况的正规码 特殊情况变为正常情况的代码 我认为单链表中这种特殊情况的删除在python中是无法完成的,

我当时在做单链表实现,我记得Linus Torvalds谈到过它

在单链表中,为了删除节点,我们应该可以访问上一个节点,然后更改它当前指向的节点

像这样

因此,无论如何,我们都应该可以访问上一个节点

但是Linus Torvalds通过在C中使用地址的概念删除了这个特例。因此head也有“前面的东西”,即指向head的head的地址。因此,他使用了C的指针和地址特性来删除特殊情况

带特殊情况的正规码

特殊情况变为正常情况的代码


我认为单链表中这种特殊情况的删除在python中是无法完成的,因为我们没有指针的概念(因此我不能在head之前进行一步)?我说的对吗?

当然可以用Python来完成。他说的是,你有一些数据结构来表示列表本身并指向列表的头部,你可以像处理第一个列表项时一样处理列表项中的指针

现在Python不是C,所以实现可能会有所不同,但原则适用。列表本身与其第一个项不是同一个对象,列表项不应具有与整个列表相同的方法,因此为它们使用不同类型的对象是有意义的

但是,这两个属性都可以使用相同名称的属性(例如
next
)指向下一个项目。因此,当您在列表中迭代时,您位于第一个项目处,“previous”项目就是列表本身,如果需要删除第一个项目,您将操作其
next
属性


当然,在现实世界中,除非作为练习,否则永远不会编写自己的Python链表类。内置的
列表更有效。

您不能在Python中使用Linus的特定技巧,因为正如您所知,Python没有指针(这样)或运算符地址。但是,您仍然可以通过为列表提供一个虚拟头节点来消除列表头的特殊情况。您可以将此作为列表设计的固有部分来完成,也可以通过创建一个额外节点并使其将第一个数据承载节点引用为下一个节点来动态完成。不管怎样,您可能要删除的所有节点都是内部节点,而不是特殊情况。

阅读您的问题时,我的第一个想法是:为什么要在python中构建单链接列表?Python提供了丰富的集合类型,您可以使用这些集合类型,而不必担心它们是作为单链表、双链表还是一些非递归数据结构(通常更容易处理)实现的

但是你的问题的答案是:Python当然允许构建一个单链表。例如,以下代码就是这样做的:

class Node:
    def __init__(self, x, next):
        self.x = x
        self.next = next

    def __str__(self):
        return "<{}, {!s}>".format(self.x, self.next)

n = Node(1, None)
n = Node(2, n)
n = Node(3, n)
print(n)  # output: <3, <2, <1, None>>>

n.next.next = n.next.next.next
print(n)  # output: <3, <2, None>>
类节点:
定义初始化(self,x,next):
self.x=x
self.next=下一个
定义(自我):
返回“”。格式(self.x,self.next)
n=节点(1,无)
n=节点(2,n)
n=节点(3,n)
打印(n)#输出:
n、 next.next=n.next.next.next
打印(n)#输出:
与C的区别在于:我们不必
malloc()
或使用指针,因为python为我们处理内存。Python有引用而不是指针,它们很相似,但更安全,更易于使用


然而,在实现链表之前,你应该考虑你的需求是关于你的集合的,也许你可以从内置的或者从集合模块中选择一个好的。

你需要两个间接的级别来按照莱纳斯的建议去做。但是,您可以在Python中通过引用一个对象来实现这一点,该对象存储了对对象或类似对象的引用(索引的索引?)。这就是说,我不认为它能如此优雅或高效地映射到Python,而且使用对象仅仅表示链接结构中的单个链接可能是非常浪费的

在Python的例子中,我只需要做额外的分支来检查从头部移除的情况,除非我缺少一些技巧

至于自己实现链表,我实际上发现很多用例中标准库是不够的。这里有一个例子:

。。。其中网格可能有10000个单元格。标准库提供的大多数链表都没有经过优化,无法以每个链表32位索引的大小存储10000多个链表,因为它们试图提供允许链表单独使用的接口(而不是像阵列一样使用单独的备份数据结构进行存储)。通常,链表的最有效使用是不拥有内存或不管理任何资源的链表。它只是以一种辅助方式链接已经在另一个数据结构中分配和管理的数据,如n元树中的128位(16字节)树节点,其中元素可以存储在层次结构的任何级别:

struct TreeNode
{
     int32 parent;       // parent index or -1 for no parent
     int32 first_child;  // first child of this node or -1
     int32 next_sibling; // next child for the parent node or -1
     int32 element;      // element data stored in this node or -1
                         // if no data is associated
};
因此,有很多用例用于实现您自己的链表和其他链接结构,对于更狭义的应用用例(网格数据结构、八叉树、四叉树、图形等),它们的效率要高得多,我不认为你可以在语言中使用这个技巧,因为语言不允许你使用两个或更多级别的指针间接寻址。Python本质上只有一个对象——与Java和C#相同。您需要类似“对象引用的引用”或“对象索引的索引”或“对象引用的对象索引”之类的内容

此外,链表在不允许您管理所有存储在内存中的位置的语言中通常也不太有用,因为您最终可能会在遍历链表时出现大量缓存未命中