Python中的双链表

Python中的双链表,python,python-3.x,doubly-linked-list,Python,Python 3.x,Doubly Linked List,我正在从事一个项目,在这个项目中,我操作了大量已排序的元素列表,我需要能够快速删除这些元素中的任何一个。因为我不需要任何类型的索引,所以我认为双链表结构最好。我找不到任何好的预制模块,所以我自己制作了: class Node: # nodes for doubly-linked lists def __init__(self, val, dll): self.val = val self.next = None self.prev = No

我正在从事一个项目,在这个项目中,我操作了大量已排序的元素列表,我需要能够快速删除这些元素中的任何一个。因为我不需要任何类型的索引,所以我认为双链表结构最好。我找不到任何好的预制模块,所以我自己制作了:

class Node: # nodes for doubly-linked lists
    def __init__(self, val, dll):
        self.val = val
        self.next = None
        self.prev = None
        self.dll = dll

class DLList: # doubly-linked lists
    def __init__(self):
        self.first = None
        self.last = None
        self.len = 0

#    def __iter__(self):
#        self.curr = self.first
#        return self
#    
#    def __next__(self):
#        if self.curr == None:
#            raise StopIteration
#        self.curr = self.curr.next
#        if self.curr == None:
#            raise StopIteration
#        return self.curr

    def append(self, val): # add a node with value val at the end of the list
        node = Node(val, self)
        node.prev = self.last
        self.last = node
        if self.first == None: # <=> if self was empty
            self.first = node
        self.len += 1

    def appendleft(self, val): # same as previous, but at the beginning of the list
        node = Node(val, self)
        node.next = self.first
        self.first = node
        if self.last == None:
            self.last = node
        self.len += 1

    def nodeat(self, i): # gives the ith node (starting at 0)
        if i == -1:
            return None
        if i > self.len or i < -1:
            raise IndexError('index out of range')
        curr = self.first
        for j in range(i):
            curr = curr.next
        return curr

    def remove(self, node): # remove a given node in the list
        if node.dll != self: #cannot remove a node that is not in the list
            raise ValueError('node not in list')
        p = node.prev
        n = node.next
        v = node.val
        node.dll = None
        if p != None:
            p.next = n
        else:
            self.first = n
        if n != None:
            n.prev = p
        else:
            self.last = p
        self.len -= 1
        return v

    def add(self, val, i): # add a node at the ith place in the list
        node = Node(val, self)
        if i > self.len:
            raise IndexError('index out of range')
        self.len += 1
        previ = self.nodeat(i)
        node.prev = previ.prev
        node.next = previ
        previ.prev = node

    def clear(self): # empty the list
        self.first = None
        self.last = None
        self.len = 0

    def extend(self, iterable): # add the elements of iterable in order at the end of the list
        for i in iterable:
            self.append(i)
            self.len += 1

    def extendleft(self, iterable): # same as previous, but at the beginning (and in reverse order)
        for i in iterable:
            self.appendleft(i)
            self.len += 1

    def dll_to_list(self): # return a python list with the elements of the doubly-linked list
        res = []
        curr = self.first
        while curr != None:
            res.append(curr.val)
            curr = curr.next
        return res

    def is_empty(self): # check whether the list is empty
        return self.len == 0
class节点:#双链接列表的节点
定义初始化(self、val、dll):
self.val=val
self.next=无
self.prev=无
self.dll=dll
类DLList:#双链接列表
定义初始化(自):
self.first=无
self.last=无
self.len=0
#定义(自我):
#self.curr=self.first
#回归自我
#    
#定义下一个(自我):
#如果self.curr==无:
#提出停止迭代
#self.curr=self.curr.next
#如果self.curr==无:
#提出停止迭代
#返回自我电流
def append(self,val):#在列表末尾添加一个值为val的节点
节点=节点(val,self)
node.prev=self.last
self.last=节点
if self.first==无:#如果self为空
self.first=节点
self.len+=1
def appendleft(self,val):#与前面相同,但位于列表的开头
节点=节点(val,self)
node.next=self.first
self.first=节点
如果self.last==无:
self.last=节点
self.len+=1
def nodeat(self,i):#给出第i个节点(从0开始)
如果i==-1:
一无所获
如果i>self.len或i<-1:
提升索引器('索引超出范围')
curr=self.first
对于范围(i)中的j:
curr=curr.next
返回货币
def remove(self,node):#删除列表中的给定节点
如果node.dll!=self:#无法删除不在列表中的节点
raise VALUERROR('节点不在列表中')
p=node.prev
n=node.next
v=node.val
node.dll=无
如果p!=无:
p、 下一个=n
其他:
self.first=n
如果n!=无:
n、 prev=p
其他:
self.last=p
self.len-=1
返回v
def add(self、val、i):#在列表的第i个位置添加一个节点
节点=节点(val,self)
如果i>self.len:
提升索引器('索引超出范围')
self.len+=1
previ=自我节点(i)
node.prev=previ.prev
node.next=previ
previ.prev=节点
def clear(self):#清空列表
self.first=无
self.last=无
self.len=0
def extend(self,iterable):#在列表末尾按顺序添加iterable的元素
因为我在iterable:
self.append(一)
self.len+=1
def extendleft(self,iterable):#与前面相同,但在开头(顺序相反)
因为我在iterable:
自左(一)
self.len+=1
def dll_to_list(self):#返回包含双链接列表元素的python列表
res=[]
curr=self.first
而咖喱!=无:
附加资源(当前值)
curr=curr.next
返回res
def为空(self):#检查列表是否为空
返回self.len==0
由于浏览列表会浪费时间检查要删除的项目是否在列表中,因此我添加了指向节点所在列表的指针,以便检查是否从错误列表中删除了内容

这些列表存储在Python字典中,在某个时候,我开始出现“节点不在列表中”错误。有人知道它是怎么出现的吗?我只使用这里列出的方法来操作列表

否则,有人知道我可以用一个编码良好的模块来代替这个模块吗


谢谢

双链接列表具有双向链接

例如:

def append(self, val): # add a node with value val at the end of the list
    node = Node(val, self)  # new node, ok
    node.prev = self.last   # ok, the new nodes prev is the last node of your list
    self.last = node        # ok, your new node is now the last of your list 
    if self.first == None:  # yeah, ok, if its empty its also the first one now
        self.first = node
    self.len += 1
但是。。。您不设置返回方向:

    node.prev.next = node  # before  node.prev = self.last   
在你的其他附属物中类似。如果在双链接列表中添加/删除内容,则必须始终清除/重置/设置两个方向上的所有链接:

(红色是附加上所有更改的变量)


从本质上说,您的列表并不完整-如果您对其进行操作/迭代,就会以意外的方式丢失内容

而没有看到试图执行删除的代码,我认为我们无法猜测您为什么会出现所描述的错误。如果您尝试删除同一个节点两次,那么您所显示的代码将引发该错误,因此我猜您是在以某种方式这样做的。我还需要注意的是,像列表这样的容器作为自己的迭代器是非常不寻常的(通常容器只是iterable,而不是迭代器本身)。是的,这是为了工作,所以我不愿意把完整的代码放在这里,但你提出了一个很好的观点。对于迭代器,它不起作用,所以我放弃了它,忘了删除这段代码。。。我下次再学怎么做!那是。。。难以置信的愚蠢,我简直不敢相信它竟然没有出现得更快!我不确定这是否导致了我的问题,因为错误消息非常具体,但我很高兴你发现了这一点。。。不过,它确实解释了我注意到的其他一些奇怪的事情。非常感谢你!不太清楚是什么导致了否决票。。。在一个这么旧的帖子上。如果您有如何提高答案质量的反馈,请进行反馈。谢谢