data_structure_3_双链表

双向链表

一种更加复杂的链表,特征是每个节点有两个链接:一个指向前一个节点,一个指向后一个节点,处理时只需要管前一个节点的后(next),后一个结节点的前(prev)即可。
特殊情况,当节点为第一个节点时prev指向空值(None),当节点为最后一个节点时next指向空值(None)
在这里插入图片描述

1.头部插入更改的代码以及原理:

		node.next = self.__head
        self.__head = node  
        node.next.prev = node 

在这里插入图片描述
2.指定位置插入
指定位置插入有两种方法:
在这里插入图片描述
在这里插入图片描述

3.删除
在这里插入图片描述
这里非常体现操作前一个节点的next,后一个节点的prev。
4.尾部插入(略)

测试代码

class Node(object):
    """节点"""

    def __init__(self, item):
        self.elem = item
        self.next = None
        self.prev = None  # 多定义一个前驱


class DoubleLinkList(object):
    """双链表"""

    def __init__(self, node=None):  # 3: 如果用户不输入头节点值 当成默认参数 None 直接创建空列表 None 其实又回到了下面一行
        # self.__head = None 1:一上来设置为空 意思是不指向任何节点 | 私有加 __ 意义:只有这个函数内部使用
        self.__head = node  # 2:在上一行的基础上人性化,用户如果先构造节点,就将头指向这个头节点 node

    def is_empty(self):
        """链表是否为空"""
        return self.__head is None  # class在变量和None进行比较时,应该使用 is。
        # 可以把比较的值直接作为返回值 如果相等即为真就是1 即返回1
        # 只要头节点指的是空那么就是空链表

    def length(self):
        """链表长度"""
        cur = self.__head  # 让它等于指向表头指向的第一个节点,cur 用于移动遍历元素
        # count 记录数量
        count = 0
        while cur is not None:  # count 从0开始的好处就是能够记录空表的长度,一个代码实现空表与一般表的长度计算
            count += 1
            cur = cur.next  # cur指向了 下一个节点
        return count

    def travel(self):
        """遍历整个链表"""
        cur = self.__head
        while cur is not None:
            print(cur.elem, end=" ")  # 打印每一个元素 空格隔开
            cur = cur.next
        print("")  # 换行

    def add(self, item):
        """链表头部添加元素,头插法"""
        node = Node(item)  # 把item这个数据封装成链表所需要的节点形式
        node.next = self.__head
        self.__head = node  # 当一开始是空的时候 头和节点都指向None 所以跑一遍上述两行还是满足的
        node.next.prev = node  # node 节点的n指向的p指向node本身

    def append(self, item):
        """链表尾部添加元素,尾插法"""
        node = Node(item)
        if self.is_empty():  # 如果链表是空的 头直接指向插入的节点
            self.__head = node
        else:
            cur = self.__head
            while cur.next is not None:
                cur = cur.next
            cur.next = node
            node.prev = cur

    def insert(self, pos, item):
        """指定位置添加元素
            :param item: 元素
            :param pos从0开始
        """
        if pos <= 0:  # 如果输入位置是<=0的默认是在头部插入
            ll.add(item)
        elif pos > self.length() - 1:
            self.append(item)
        else:
            cur = self.__head
            count = 0
            while count < pos:  # 不需要两个游标只需要一个了
                count += 1
                cur = cur.next
                # 当循环退出后 cur指向pos位置
            node = Node(item)
            node.next = cur  # 这四句话是完成指定位置插入的操作过程
            node.prev = cur.prev
            cur.prev.next = node
            cur.prev = node

    def remove(self, item):
        """删除节点,找到和你想删除的数一样的数"""
        cur = self.__head
        while cur is not None:
            if cur.elem == item:
                # 先判断此节点是否是头节点 如果是头节点
                if cur == self.__head:
                    self.__head = cur.next
                    if cur.next:  # 判断链表是否只有一个元素
                        cur.next.prev = None
                else:
                    cur.prev.next = cur.next
                    if cur.next:
                        cur.next.prev = cur.prev
                break
            else:  # 移动
                cur = cur.next

    def search(self, item):
        """链表查找节点是否存在,并返回True或者False"""
        cur = self.__head
        while cur is not None:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        return False


# 测试代码
if __name__ == "__main__":
    ll = DoubleLinkList()
    print(ll.is_empty())
    print(ll.length())

    ll.append(1)
    print(ll.is_empty())
    print(ll.length())

    ll.append(2)
    ll.add(8)
    ll.append(3)
    ll.append(4)
    ll.append(5)
    ll.append(6)
    ll.insert(-1, 9)
    ll.travel()
    ll.insert(2, 100)
    ll.travel()
    ll.insert(10, 200)
    ll.travel()
    ll.remove(200)
    ll.travel()
    ll.insert(20, 200)
    ll.travel()
    ll.insert(21, 200)
    ll.travel()
    ll.remove(200)
    ll.travel()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值