双循环链表

线性存储

数组和链表都是一维结构,以线性结构存储数据。

数组

数组和计算机内存结构保持一致,现有的编程语言提供了语言层面对数组的支持,数组支持随机访问,可以按照索引高效读取和存储。

一般来说,数组在初始化时,已固定大小。当数组存储已满,需要再存储额外的数据,则需要申请更大的一个数组,把原来的数据全部搬到新数组。 这在某些场景下是不合理的,从而引出另一种存储结构:链表

单链表

单链表是另一种基本的链式存储结构,很多其它的数据结构均以它为基础构建。

仅保存head指针

仅保存head节点指针的单链表,当遍历时候,可以从head节点开始访问遍历,可以在头节点添加和删除。

保存head指针和tail指针

多记录一个tail指针,可以方便的在链表的尾部增加节点。(但在尾部删除节点仍然不行,由于删除时需要用到当前节点的前一个节点)

单循环链表

单循环链表仅仅是把尾部节点的下一个节点指向了头结点。

双循环链表

双循环链表是比较通用且功能丰富的数据结构,实际应用场景比较多。图如下:

双循环链表

第一个节点是一个哨兵节点,头结点的数据域可以用来存储某些数据,也可以不用。哨兵节点的关键作用是,使得操纵链表时的代码逻辑比较统一,如果没有哨兵节点,则在添加和删除节点的时候,需要特殊处理头结点为空的情况。通过添加一个额外的哨兵节点,简洁实用。

双循环链表-初始状态

初始状态,头结点的prev和next指针均指向自身。这也是判断双循环链表为空的逻辑。

双循环链表-头部添加

在双循环链表头部添加数据流程:
1. 构造一个新节点,首先设置该新节点的数据域和指针,设置新节点的next指针指向head的next,prev指针指向head
2. 设置head->next的prev指向新节点
3. 设置head的next指向当前节点

可以看到,即使链表为空(即仅包含head节点时),上述添加流程也能正常工作,这体现了哨兵节点的作用。

比如从头部依次添加整数序列,[1, 2, 3, 4, 5],到链表中,链表的结构如下:

head -> 5 -> 4 -> 3 -> 2 -> 1 ->

双循环链表-尾部添加

尾部添加流程和上述的头部添加类似, 但最终数据顺序和原来相反,

比如从尾部依次添加整数序列,[1, 2, 3, 4, 5],到链表中,链表的结构如下:

1 -> 2 -> 3 -> 4 -> 5 -> head ->

可见不管是从链表头部添加,还是从尾部添加,最终我们都可以通过从head节点开始遍历,或者通过next指针遍历,或者通过prev指针开始遍历,都可以方便的遍历整个链表。

双循环链表-头部删除

逻辑看指针图即可,不再赘述。

双循环链表-尾部删除

逻辑看指针图即可,不再赘述。

双循环链表 -> 其它数据结构

可以看到双循环链表可以在头部和尾部进行添加和删除,且时间复杂度为O(1), 空间复杂度为O(1),这是个好兆头。 正好可以用来实现栈和队列

Python参考实现

详细源码可参见github

class DNode(object):
    def __init__(self, v):
        self.v = v
        self.next = self
        self.prev = self

class DoubleCircleList(object):
    '''双循环链表'''
    def __init__(self):
        self.__head = DNode(None)

    def add_head(self, v):
        node = DNode(v)
        self.insert_after(self.__head, node)

    def add_tail(self, v):
        node = DNode(v)
        self.insert_before(self.__head, node)

    def del_head(self):
        if self.__head.next != self.__head:
            return self.del_node(self.__head.next)

    def del_tail(self):
        if self.__head.next != self.__head:
            return self.del_node(self.__head.prev)

    def get_head(self):
        if self.__head.next != self.__head:
            return self.__head.next

    def get_tail(self):
        if self.__head.next != self.__head:
            return self.__head.prev

    def insert_after(self, node1, node2):
        node2.next = node1.next
        node2.prev = node1
        node1.next.prev = node2
        node1.next = node2

    def insert_before(self, node1, node2):
        node2.next = node1
        node2.prev = node1.prev
        node1.prev.next = node2
        node1.prev = node2

    def del_node(self, node):
        node.next.prev = node.prev
        node.prev.next = node.next
        return node

    def is_empty(self):
        return self.__head.next == self.__head

    def iterator(self):

        class Iter(object):
            def __init__(self, head):
                self.__head = head

            def __iter__(self):
                node = self.__head.next
                while node != self.__head:
                    yield node.v
                    node = node.next
        return Iter(self.__head)

    def reverse_iterator(self):

        class Iter(object):
            def __init__(self, head):
                self.__head = head

            def __iter__(self):
                node = self.__head.prev
                while node != self.__head:
                    yield node.v
                    node = node.prev
                node = self.__head.next

        return Iter(self.__head)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值