双链表

概念

单链表只有一个方向的链接,只能做一个方向的扫描和逐步操作,即使增加了尾结点引用,也只能支持O(1)时间的首端元素插入/删除和尾端加入。如果希望两端插入和删除操作都能高效完,就必须修改结点的基本设计,加入另一方向的链接,这样就得到双向链接表,简称双链表。

为了支持首尾两端的高效 操作,双链表应该采用如图所示的结构,包含一个尾结点引用域

双链表结点操作:

  • 结点删除,只要掌握着双链表 里的一个结点,就可以把它同表中取下,并把 区域结点正确链接好,如下图所示:

  • 示例代码,假设定结点的下一结点引用域为next,前一结点的引用域为prev
    p.prev.next = p.next
    p.next.prev = p.prev

双链表类

class LNode():
    def __init__(self, elem, next_=None):
        self.elem = elem
        self.next = next_
class DLNode(LNode):
    def __init__(self, elem, prev=None, next_=None):
        LNode.__init__(self, elem, next_)
        self.prev = prev
class DLList(LList):
    def __init__(self):
        LList.l__init__(self)
    def prepend(self,elem):
        p = DLNode(elem,None,self._head)
        if self._head is None:
            self._head = p
        else:
            p.next.prev = p
        self._head = p
    def append(self, elem):
        p = DLNode(elem, self._rear, None)
        if self._head is None:
            self._head = p
        else:
            p.prev.next = p
        self._rear = p
    def pop(self):
        if self._head is None:
            raise LinkedListUnderflow("in pop of DLList")
        e = self._head.elem
        self._head = self._head.next
        if self._head is not None:
            self._head.prev = None
        return e
    def pop_last(self):
        if self._head is None:
            raise LinkedListUnderflow("in pop_last")
        e = self._rear.elem
        self._rear = self._rear.prev
        if self._rear is None:
            self._head = None
        else:
            self._rear.next = None
        return e

循环双链表

双链表也可以定义为循环链表,也就是说,让表尾结点next域指向表的首结点,而让表首结点的prev域指向尾结点,如图所示

由于这种表里存在双向链接,无论是掌握着表的首结点还是尾结点,都能高效首先首尾端的元素加入/删除操作(O(1)复杂度)

 

posted @ 2020-08-04 15:46  你的莫  阅读(191)  评论(0)    收藏  举报