首页 > 技术文章 > python实现双向链表

longyunfeigu 2018-07-26 16:20 原文

class Node(object):
    def __init__(self, data):
        self.data = data
        self.next = None
        self.pre = None

class DLinkList(object):
    def __init__(self, node=None):
        self.__head = node
        self.cur = self.__head

    def is_empty(self):
        """
        链表是否为空
        :return:
        """
        return self.__head == None

    def __len__(self):
        """
        链表长度
        :return:
        """
        count = 0
        cur = self.__head
        # while循环条件不同,count也应该从不同开始。这里的条件可以有两种
        # cur None   cur.next None,采用cur None 是因为 count=0 正好满足空链表的情况
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def append(self, data):
        """
        尾部添加
        :param data:
        :return:
        """
        node = Node(data)
        if self.is_empty():
            self.__head = node
            self.cur = self.__head
            return
        cur = self.__head
        while cur.next != None:
            cur = cur.next
        # 退出while循环的时候, 此时当前节点cur 的位置是最后一个节点
        cur.next = node
        node.pre = cur

    def add(self, data):
        """
        头部添加
        :return:
        """
        node = Node(data)
        if self.is_empty():
            self.__head = node
            return 
        node.next = self.__head
        self.__head.pre = node
        self.__head = node

        self.cur = self.__head

    def __iter__(self):
        return self

    def __next__(self):
        if self.cur != None:
            data = self.cur.data
            self.cur = self.cur.next
            return data
        else:
            raise StopIteration

    def pop(self):
        """
        从末尾弹出元素
        :return:
        """
        pre = None
        cur = self.__head
        while cur.next != None:
            pre = cur
            cur = cur.next
        pre.next = None

    def remove(self, data):
        """
        删除指定数值元素
        :param data:
        :return:
        """
        cur = self.__head
        pre = None
        while cur != None:
            if cur.data == data:
                # 如果是头节点
                if cur == self.__head:
                    self.__head = cur.next
                    cur.next.pre = None

                    self.cur = self.__head
                # 中间节点和尾节点
                else:
                    pre.next = cur.next
                    cur.next.pre = pre
                break
            else:
                pre = cur
                cur = cur.next

    def insert(self, pos, data):
        """
        在指定位置插入元素,pos 从 0 开始
        :param pos:
        :param data:
        :return:
        """
        if pos == 0:
            self.add(data)
        elif pos >= len(self):
            self.append(data)
        else:
            count = 0
            node = Node(data)
            cur = self.__head
            pre = None
            while count < pos:
                pre = cur
                cur = cur.next
                count += 1
            pre.next = node
            node.pre = pre
            node.next = cur
            cur.pre = node

if __name__ == '__main__':
    l = DLinkList()
    l.append(1)
    l.append(2)
    l.add(3)
    l.insert(1,77)
    l.pop()
    for i in l:
        print(i)

总结:

  1. 对于一些逻辑判断可能会比较复杂,所以应该先按照正常逻辑处理一般情况,然后再在之前写的代码的基础上考虑特殊情况
  2. while循环的条件和外面的计数器是相关的,对于while循环的理解一定得到位,而且当while循环退出的时候变量处于的值应该就是临界条件,明确什么条件走入循环,循环体和循环条件的同异步关系
  3. 面向对象的思想正好体现在这个方面,屏蔽外界操作,有些操作内部完成,封装
  4. python变量的实质,a=5, a并不是5这个内存地址的别名,而是开辟两块空间,一块是5,一块存5的地址
  5. 分清一个变量的使用和引用,放在等号右边就是使用这个变量

推荐阅读