在Python中实现双链表

时间:2015-04-14 03:09:42

标签: python linked-list

我试图用以下函数实现双向链表:

_insertItemAfterNode(self,index) 

_nodeBeforeIndex(self, index)



insertItemAtTheFront(self,item)

insertItemAtTheEnd(self,item)

insertItemAtIndex(self, index, item)

最后三个函数应该使用前两个私有方法。 这是我到目前为止,但我似乎无法工作。任何帮助表示赞赏!!!

# DoublyLinkedLists

class Node(object):

    def __init__(self, prev = None, data=None, next = None):
        self._prev = prev
        self._data = data
        self._next = next

    def __str__(self):
        return str(self._data)
    def __repr__(self):
        return "Node(%s,%s,%s)" % (repr(self._prev), repr(self._data), repr (self._next))

    def __eq__(self, other):
        if other == None:
            return False
        else:
            return self._prev == other._prev and self._data == other._data and self._next == other._next`enter code here`

class DoublyLinkedList(object):

    def __init__(self):
        self._first = Node(None, None, None)
        self._length = 0
        self._last = Node(None, None, None)

    def __len__(self):
        return self._length

    def _insertItemAfterNode(self,item,aNode):
        newNode = Node(aNode._prev, item, aNode._next)
        aNode._next= newNode._prev
        aNode._prev=newNode._next
        self._length += 1

    def _nodeBeforeIndex(self, index):
        if 0 <= index <= self._length:
            aNode = self._first
            for i in range(index):
                aNode = aNode._next
            return aNode
        else:
            raise IndexError

    def _nodeAfterIndex(self, index):
        if 0<= index <= self.length:
            aNode = self._last
            for i in range(index):
                aNode = aNode._prev
            return aNode
        else:
            raise IndexError

    def __getitem__(self, index):
        return self._nodeBeforeIndex(index)._next._data

    def insertAtEnd(self, item):
        self._nodeAfterIndex(item)        

    def __iter__(self):
        return DoublyLinkedListIterator(self)

    def __setitem__(self, index, item):
        self._nodeBeforeIndex(index)._next._data = item

    def insertItemAtTheFront(self, item):
        self._insertItemAfterNode(item, self._nodeBeforeIndex(0))

    def insertItemAtTheEnd(self, item):
        self._insertItemAfterNode(item, self._nodeBeforeIndex(self._length))

    def insertItemAtIndex(self, index, item):
        '''Valid range 0 <= index <= length.'''
        self._insertItemAfterNode(item, self._nodeBeforeIndex(index))

    def __iter__(self):
        return DoublyLinkedListIterator(self)

    def __repr__(self):
        #used by print in abscence of __str__ .
        plist = []
        for item in self:
            plist.append(item)
        return "DoublyLinkedList(%s)" % str(plist)

class DoublyLinkedListIterator(object):

    def __init__(self, aList):
        self._list = aList
        self._currentIndex = -1
        self._currentNode = self._list._first

    def __iter__(self):
        return self

    def __next__(self):
        if self._currentIndex == self._list._length - 1:
            raise StopIteration
        else:
            self._currentIndex += 1
            self._currentNode = self._currentNode._next
            return self._currentNode._data

def main():

    x = DoublyLinkedList()

    x.insertItemAtTheEnd(45)

    print(x)

main()

2 个答案:

答案 0 :(得分:1)

您的代码有些奇怪。让我们深入研究我发现的第一个问题:

def _insertItemAfterNode(self,item,aNode):
    newNode = Node(aNode._prev, item, aNode._next)
    aNode._next= newNode._prev
    aNode._prev=newNode._next
    self._length += 1

假设你有:

prevNode <-> aNode <-> nextNode

您现在创建一个newNode,其前一个指向prevNode,后续指向nextNode。然后你反转aNode的指针。 prevNode仍然认为其后续节点为aNode,但aNode现在认为其后续节点为prevNode

              /---------\
       /----> aNode <    v 
prevNode <--------/  \-- nextNode
       ^                 ^
        \---- newNode --/

这几乎不是你想要的:

prevNode <-> aNode <-> newNode <-> nextNode

这是一个更好的版本:

def _insertItemAfterNode(self,item,aNode):
    # If the new Node follows aNode, than its preceeding node is aNode,
    # not aNode._prev!
    newNode = Node(aNode, item, aNode._next)
    # Now we need to make aNode point at its new following Node, newNode
    aNode._next = newNode
    # And finally, we need to make the following Node notice that 
    # its preceeding Node has changed.
    newNode._next._prev = newNode
    self._length += 1

这并不关心任何边缘情况,例如,如果aNode是链表中的最后一个节点,该怎么办。

我建议你拿出一张纸,画出你需要为每个操作改变不同链接的方式,因为很难把这一切都记在脑后。

确保查看所有边缘情况,即。放入一个空列表,将项目放入第一个和最后一个位置。

最后,在改变链接时,总是仔细检查每个链接指向每条指令的位置,而不是意外丢弃任何节点。

答案 1 :(得分:1)

我发现您的代码存在两个直接问题。可能还有更多我没有注意到的问题,但这些问题可能会阻止您在修复之前看到任何其他问题。

第一个问题非常简单。您的_first课程中有两个前哨节点_lastDoublyLinkedList。但是,它们没有相互关联,所以当稍后添加更多节点时,它们将不会像它们应该那样连接到两个标记。

您可以通过更改__init__方法来解决此问题:

def __init__(self):
    self._first = Node(None, None, None)
    self._length = 0
    self._last = Node(self._first, None, None)    # pass first node as an arg here
    self._first._next = self._last                # make a link back too

第二个问题是你如何添加节点。有几个地方您要从节点的_prev_next属性中分配值,而不是引用节点本身。

让我们想一下包含AC个节点的列表,并希望在它们之间插入B。您需要将B的节点链接到AC,然后修改CA以链接回来。在您的代码中,AaNodeBnewNodeC为(开始时)aNode._next

def _insertItemAfterNode(self, item, aNode):
    newNode = Node(aNode, item, aNode._next)     # link B to A and C
    aNode._next._prev = newNode                  # link C back to B
    aNode._next = newNode                        # and A to B too!
    self._length += 1