快速了解——数据结构【Python】实现模拟单向链表

数据结构

1、概述

        存储、组织数据的方式,包括列表、元组、集合、字典、队列、栈、链表。

2、分类
        线性结构
        1.概述

                所有节点 只有一个 直接前驱节点 和 一个 直接后继节点

        2.存储分类
  • 顺序表:连续的存储

        存储结构:信息区,数据区

        存储方式:1. 一体式存储:替换只能 整体搬迁

                          2. 分离式存储

        扩充方式:1. 增加 固定数目 的存储位置

                          2. 容量加倍

  • 链表:非连续 的存储

        结构:由节点(Node)组成,用 “链条” 连接起来

        节点组成:1. 数值域 item(元素域):存数据的

                          2. 地址域 next(链接域):存下个节点的地址

                          3. 变量 head 指向链表的 头节点(首节点)

        链表分类:单向链表、单向循环链表、双向链表、双向循环链表

3、单向链表代码实现

需求1:定义节点类,单向链表类,并设置初始化

# 1、定义SingleNode类,表示节点类
class SingleNode:
    # 初始化节点
    def __init__(self, item):
        self.item = item    # 元素域:存储具体数据
        self.next = None    # 链接域:存储下个节点地址

# 2、定义SingleLinkedList类,表示(单向)链表
class SingleLinkedList:
    # 2.1 初始化链表
    def __init__(self, node=None):
        # head(默认)指向 链表中的第1个节点
        self.head = node

需求2:在链表类中,定义函数:判断链表是否为空,为空返回True

# 2.2 判断链表 是否为空
    def is_empty(self):

        # 写法 1: if、else方法
        # if self.head == None:
        #     return True
        # else:
        #     return False

        # 写法 2: 三元
        # return True if self.head == None else False

        # 写法 3: 最终版
        return self.head == None

需求3:在链表类中,定义函数:查看链表长度

# 2.3 查看链表长度
    def length(self):
        # 1. 定义 当前节点 cur,初始值为 头节点
        cur = self.head
        # 2. 定义计数器, 记录: 节点个数
        count = 0
        # 3. 判断 cur(当前节点)是否为None, 如果不是, 就一直循环
        while cur is not None:
            # 4. 进这里, 说明是1个非空节点, 计数器 + 1
            count += 1
            # 5. 当前节点判断后, cur指向下1个节点
            cur = cur.next
        # 6. 返回计数结果
        return count

需求4:在链表类中,定义函数:遍历链表并打印结果

# 2.4 遍历链表
    def travel(self):
        # 1、定义cur变量,用于记录:链表中的 每个节点
        cur = self.head
        # 2. 判断当前节点是否为空, 不为空, 就一直循环
        while cur is not None:
            # 3. 不为空,就打印节点信息
            print(cur.item)
            # 4. cur指向下1个节点
            cur = cur.next

需求5:在链表类中,定义函数:在头部 添加元素

# 2.5 在链表 头部 添加元素
    def add(self, item):
        # 1、根据输入,创建新节点
        new_node = SingleNode(item)
        # 2、设置新节点的 地址域 为 头节点
        new_node.next = self.head
        # 3、更新 head指向 新的头节点
        self.head = new_node

需求6:在链表类中,定义函数:在尾部 添加元素

# 2.6 在链表 尾部 添加元素
    def append(self, item):
        # 1、根据输入,创建新节点
        new_node = SingleNode(item)
        # 2. 判断链表是否为空
        if self.head == None:
            # 链表为空, 则新节点就是头部节点
            self.head = new_node
        else:
            # 3. 链表不为空,获取链表的最后1个节点
            # 3.1 创建cur变量, 默认指向头部节点
            cur = self.head
            # 3.2 只要当前节点的地址域不为 None, 就一直获取
            while cur.next is not None:
                # 更新当前节点
                cur = cur.next
            # 3.3 循环结束, 说明获取的节点就是最后1个节点(它的地址域为None)
            # 设置当前(最后1个节点)的地址域为: 新的节点
            cur.next = new_node

需求7:在链表类中,定义函数:在指定位置 添加元素

# 2.7 在 指定位置 添加元素
    def insert(self, pos, item):    # pos为指定位置
        # 1. 指定位置若 <= 0 ,就在开头添加
        if pos <= 0:
            self.add(item)
        # 2. 指定位置若 >= 链表长度,就在结尾添加
        elif pos >= self.length():
            self.append(item)
        # 3. 否则,即在链表中间 添加
        else:
            # 4. 创建新节点
            new_node = SingleNode(item)
            # 5. 创建cur变量, 指向: 插入位置前的那个节点. 默认: 头节点
            cur = self.head
            # 6. 定义count变量, 用于: 计数, 获取插入位置前的值
            count = 0
            # 7. 获取插入位置前的那个元素
            while count < pos - 1:
                cur = cur.next
                count += 1      # 计数器 + 1
            # 8. 设置新节点的地址域为: 当前节点的地址域
            new_node.next = cur.next
            # 9. 设置当前节点的地址域为: 新的节点
            cur.next = new_node

需求8:在链表类中,定义函数:根据节点内容 删除指定节点

 # 2.8 删除指定节点
    def remove(self, item):
        # 1. 定义变量 cur, 从头节点开始, 获取被删除的节点
        cur = self.head
        # 2. 定义变量 pre, 表示: 被删除节点的 前置节点
        pre = None
        # 3. 只要 cur不为空, 我们就一直遍历, 获取每个节点
        while cur is not None:
            # 4. 判断当前节点的数值域 是否和 要删除的元素值 相同
            # 4.1 相同, 则要被删除
            if cur.item == item:
                # 4.1.1 如果是头部节点, 直接用 head 指向 cur.next即可
                if cur == self.head:
                    self.head = cur.next
                # 4.1.2 如果不是头部节点, 用 pre的地址域 指向 当前节点的地址域(即下个节点) 完成删除
                else:
                    pre.next = cur.next
                # 核心细节: 删除元素后, 循环终止.
                break
            else:
                # 4.2 如果不同, 说明当前节点不是要被删除的节点, 我们继续判断下 1个节点
                pre = cur       # 当前节点(检验过) 充当前置节点
                cur = cur.next

需求9:在链表类中,定义函数:查找节点是否存在,存在返回True

# 2.9 查找节点是否存在
    def search(self, item):
        # 1. 定义变量 cur, 记录每个节点, 初值为: 头部节点.
        cur = self.head
        # 2. 如果 cur节点不为空, 我们就一直遍历
        while cur is not None:
            # 3. 判断当前节点的item值, 是否和要查找的item值一致
            if cur.item == item:
                # 找到啦!返回 True
                return True
            # 4. 没找到,继续判断下一个节点
            cur = cur.next
        # 5. 整个循环结束, 没有找到, 返回 False
        return False

需求10:在 main方法中测试结果

# 3. 在 main方法中测试
if __name__ == '__main__':
    # 3.1 创建单个节点
    sn1 = SingleNode('小林')
    print(sn1.item)         # 当前节点的: 元素域值
    print(sn1.next)         # 当前节点的: 地址域值

    # 3.2 创建链表
    linked_list = SingleLinkedList(sn1)
    print(f'目前的头节点是:{linked_list.head}')

    # 3.3 判断链表是否为空
    print(linked_list.is_empty())

    # 3.4 打印链表的长度(元素个数)
    print(f'链表长度为:{linked_list.length()}')

    # 3.5 打印链表内容
    linked_list.travel()

    # 3.6 演示在链表 头部 添加
    linked_list.add('小陈')
    linked_list.add('小月')

    # 3.7 演示在链表 尾部 添加
    linked_list.append('小雪')
    linked_list.append('小念')

    # 3.8 演示在链表 中间 添加
    linked_list.insert(3, '小龙')
    # 再次查看链表内容
    linked_list.travel()

    # 3.9 演示 删除
    linked_list.remove('小龙')

    # 3.10 演示 查找
    print(linked_list.search('小林'))

完整代码如下:

# 1、定义SingleNode类,表示节点类
class SingleNode:
    # 初始化节点
    def __init__(self, item):
        self.item = item    # 元素域:存储具体数据
        self.next = None    # 链接域:存储下个节点地址

# 2、定义SingleLinkedList类,表示(单向)链表
class SingleLinkedList:
    # 2.1 初始化链表
    def __init__(self, node=None):
        # head(默认)指向 链表中的第1个节点
        self.head = node

    # 2.2 判断链表 是否为空
    def is_empty(self):
        return self.head == None

    # 2.3 查看链表长度
    def length(self):
        # 1. 定义 当前节点 cur,初始值为 头节点
        cur = self.head
        # 2. 定义计数器, 记录: 节点个数
        count = 0
        # 3. 判断 cur(当前节点)是否为None, 如果不是, 就一直循环
        while cur is not None:
            # 4. 进这里, 说明是1个非空节点, 计数器 + 1
            count += 1
            # 5. 当前节点判断后, cur指向下1个节点
            cur = cur.next
        # 6. 返回计数结果
        return count

    # 2.4 遍历链表
    def travel(self):
        # 1、定义cur变量,用于记录:链表中的 每个节点
        cur = self.head
        # 2. 判断当前节点是否为空, 不为空, 就一直循环
        while cur is not None:
            # 3. 不为空,就打印节点信息
            print(cur.item)
            # 4. cur指向下1个节点
            cur = cur.next

    # 2.5 在链表 头部 添加元素
    def add(self, item):
        # 1、根据输入,创建新节点
        new_node = SingleNode(item)
        # 2、设置新节点的 地址域 为 头节点
        new_node.next = self.head
        # 3、更新 head指向 新的头节点
        self.head = new_node

    # 2.6 在链表 尾部 添加元素
    def append(self, item):
        # 1、根据输入,创建新节点
        new_node = SingleNode(item)
        # 2. 判断链表是否为空
        if self.head == None:
            # 链表为空, 则新节点就是头部节点
            self.head = new_node
        else:
            # 3. 链表不为空,获取链表的最后1个节点
            # 3.1 创建cur变量, 默认指向头部节点
            cur = self.head
            # 3.2 只要当前节点的地址域不为 None, 就一直获取
            while cur.next is not None:
                # 更新当前节点
                cur = cur.next
            # 3.3 循环结束, 说明获取的节点就是最后1个节点(它的地址域为None)
            # 设置当前(最后1个节点)的地址域为: 新的节点
            cur.next = new_node

    # 2.7 在 指定位置 添加元素
    def insert(self, pos, item):    # pos为指定位置
        # 1. 指定位置若 <= 0 ,就在开头添加
        if pos <= 0:
            self.add(item)
        # 2. 指定位置若 >= 链表长度,就在结尾添加
        elif pos >= self.length():
            self.append(item)
        # 3. 否则,即在链表中间 添加
        else:
            # 4. 创建新节点
            new_node = SingleNode(item)
            # 5. 创建cur变量, 指向: 插入位置前的那个节点. 默认: 头节点
            cur = self.head
            # 6. 定义count变量, 用于: 计数, 获取插入位置前的值
            count = 0
            # 7. 获取插入位置前的那个元素
            while count < pos - 1:
                cur = cur.next
                count += 1      # 计数器 + 1
            # 8. 设置新节点的地址域为: 当前节点的地址域
            new_node.next = cur.next
            # 9. 设置当前节点的地址域为: 新的节点
            cur.next = new_node

    # 2.8 删除指定节点
    def remove(self, item):
        # 1. 定义变量 cur, 从头节点开始, 获取被删除的节点
        cur = self.head
        # 2. 定义变量 pre, 表示: 被删除节点的 前置节点
        pre = None
        # 3. 只要 cur不为空, 我们就一直遍历, 获取每个节点
        while cur is not None:
            # 4. 判断当前节点的数值域 是否和 要删除的元素值 相同
            # 4.1 相同, 则要被删除
            if cur.item == item:
                # 4.1.1 如果是头部节点, 直接用 head 指向 cur.next即可
                if cur == self.head:
                    self.head = cur.next
                # 4.1.2 如果不是头部节点, 用 pre的地址域 指向 当前节点的地址域(即下个节点) 完成删除
                else:
                    pre.next = cur.next
                # 核心细节: 删除元素后, 循环终止.
                break
            else:
                # 4.2 如果不同, 说明当前节点不是要被删除的节点, 我们继续判断下 1个节点
                pre = cur       # 当前节点(检验过) 充当前置节点
                cur = cur.next

    # 2.9 查找节点是否存在
    def search(self, item):
        # 1. 定义变量 cur, 记录每个节点, 初值为: 头部节点.
        cur = self.head
        # 2. 如果 cur节点不为空, 我们就一直遍历
        while cur is not None:
            # 3. 判断当前节点的item值, 是否和要查找的item值一致
            if cur.item == item:
                # 找到啦!返回 True
                return True
            # 4. 没找到,继续判断下一个节点
            cur = cur.next
        # 5. 整个循环结束, 没有找到, 返回 False
        return False

# 3. 在 main方法中测试
if __name__ == '__main__':
    # 3.1 创建单个节点
    sn1 = SingleNode('小林')
    print(sn1.item)         # 当前节点的: 元素域值
    print(sn1.next)         # 当前节点的: 地址域值

    # 3.2 创建链表
    linked_list = SingleLinkedList(sn1)
    print(f'目前的头节点是:{linked_list.head}')

    # 3.3 判断链表是否为空
    print(linked_list.is_empty())

    # 3.4 打印链表的长度(元素个数)
    print(f'链表长度为:{linked_list.length()}')

    # 3.5 打印链表内容
    linked_list.travel()

    # 3.6 演示在链表 头部 添加
    linked_list.add('小陈')
    linked_list.add('小月')

    # 3.7 演示在链表 尾部 添加
    linked_list.append('小雪')
    linked_list.append('小念')

    # 3.8 演示在链表 中间 添加
    linked_list.insert(3, '小龙')

    linked_list.travel()
    # 3.9 演示 删除
    linked_list.remove('小龙')

    # 3.10 演示 查找
    print(linked_list.search('小林'))

感谢阅读!一起努力练习吧~

  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值