Python-模拟单链表

 一、数据结构

根据数据结构中数据之间的关系,将数据结构分类为:

线性结构:线性结构就是数据结构中各个结点具有线性关系。

非线性结构:非线性结构就是数据结构中各个结点之间具有多个对应关系。

二、线性结构存储方式的分类

线性结构的实际存储方式,分为两种:

1、顺序表:将元素顺序的存放在一块连续的存储区里面,元素间的顺序关系由它们的存储顺序自然表示。

2、链表:将元素存放在通过链接构造起来的一系列存储块中,存储区域是非连续的。

3、顺序表和链表的优缺点

链表存储方式由于不需要按照顺序存储,在插入、删除元素时比顺序存储要快,但是在查找一个节点时要比顺序存储要慢。

三、单链表

        单链表(Singly Linked List)是一种数据结构,由一系列节点组成。每个节点都包含两部分:数据和指向下一个节点的引用(或链接)。单链表中的第一个节点称为头节点,最后一个节点的下一个引用通常指向空值(None)

四、python代码实现单链表

#定义节点类
class Node:
    #初始化节点
    def __init__(self, item):
        self.item = item	#存储具体数据
        self.next = None	#存储下一个节点的地址
#获取节点元素:node.item
#获取下一个节点:node.next

#表示单链表
class SingleLinkedList:
    #初始化链表
    def __init__(self, node=None):
        #默认指向链表中第一个节点,头结点
        self.head = node

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

    #链表长度
    def length(self):
        #定义变量,记录当前节点,初始值为头节点
        cur = self.head
        #定义计数器,用来记录节点个数
        count = 0
        #循环判断当前节点是否为空
        while cur is not None:
            #进入循环里面,说明节点不为空,计数器加一
            count += 1
            #cur变量指向下一个节点
            cur = cur.next
        #返回计数器结果
        return count

    # 链表遍历
    def travel(self):
        # 定义变量,记录当前节点,初始值为头节点
        cur = self.head
        # 循环判断当前节点是否为空
        while cur is not None:
            # 打印cur的item值
            print(cur.item)
            # cur变量指向下一个节点
            cur = cur.next

    # 链表头部添加元素
    def add(self, item):
        # 根据元素值,创建节点
        new_node = Node(item)
        # 新节点的地址域为头结点
        new_node.next = self.head
        # 更新头结点指向为新节点
        self.head = new_node

    # 链表尾部添加新元素,(最后一个节点的next指向为None)
    def append(self, item):
        # 根据元素值,创建节点
        new_node = Node(item)
        # 判断链表是否为空,为空时,头结点指向新的节点
        if self.is_empty():
            self.head = new_node
        else:
            # 定义变量,记录当前节点,初始值为头节点
            cur = self.head
            # 当前节点的地址域不为空时,就一直循环获取链表中的节点
            while cur.next is not None:
                # cur变量指向下一个节点
                cur = cur.next
            # 走到这里说明当前节点的地址域为None,设置当前节点的地址域为新节点
            cur.next = new_node

    # 指定位置添加元素
    # pos:添加的位置
    def insert(self, pos, item):
        # 判断要添加的位置,如果小于等于0,就在头部添加
        if pos <= 0:
            # 调用在头部添加元素
            self.add(item)
        # 判断要添加的位置,如果打于等于链表长度,就在尾部添加
        elif pos > self.length():
            # 调用在尾部添加元素
            self.append(item)
        else:
            # 根据元素值,创建节点
            new_node = Node(item)
            # 定义变量,记录当前节点,初始值为头节点
            cur = self.head
            # 定义count变量,获取插入位置前的值
            count = 0
            # 循环判断获取插入位置前的那个元素
            while count < pos - 1:
                cur = cur.next
                count += 1
            # 设置新节点的地址域为当前节点的地址域
            new_node.next = cur.next
            # 设置当前节点的地址域为新节点
            cur.next = new_node
##解释为什么要先把新的节点的地址域设置为当前节点的地址域,再将当前节点的地址域设置为新节点的。
#例子说明:间谍A与间谍B,一直是单向联络,他们只知道自己的下家是谁,,间谍A是间谍B的上家,有一天间谍业务太过繁忙,
# 间谍总部派出间谍X去协助A、B,间谍之间有一个联络密码本叫next上面记录了下家的联络方式,但是密码本上面只能写一个
# 下家的联络方式,一旦修改后再也找不到之前的,间谍X想联络间谍B,得先找到他的上家间谍A,间谍A把密码本next给间谍x,
# 因为间谍x的密码本上面的联系方式是间谍A给的,所有间谍x.next = 间谍A.next 因为间谍A把间谍B的联络方式next给了间谍x,
# 以后就由间谍A来联络间谍X,间谍X来联系间谍B,也就是说间谍A的next上面就写了X的联络方式,间谍A.next = 间谍X

    # 删除节点
    def remove(self, item):
        # 定义变量,记录当前节点,初始值为头节点
        cur = self.head
        # 定义pre变量,表示要被删除的节点的前一个节点
        pre = None
        # 当cur不为空时,一直循环
        while cur is not None:
            # 判断当前节点的元素域是否是要删除的节点的元素域
            if item == cur.item:
                # 判断要删除的节点是否是头节点
                if cur == self.head:
                    # 让头结点指向当前节点的下一个节点
                    self.head = cur.next
                # 如果不是头结点
                else:
                    # 当前节点的前一个节点地址域指向当前节点的地址域(下一个节点)
                    pre.next = cur.next
                break
            else:
                pre = cur
                cur = cur.next
    #per: 当前节点的前一个节点

    #判断链表是否存在该元素
    def sreach(self, item):
        # 定义变量,记录当前节点,初始值为头节点
        cur = self.head
        # 当节点不为空时,一直循环
        while cur is not None:
            # 判断当前节点的item值和要查找的item值是否一致
            if cur.item == item:
                return True
            # 走这里说明没有匹配上,继续判断下一个节点
            cur = cur.next
        return False

if __name__ == '__main__':
    #创建单个节点
    p1 = Node('强子')
    print(p1.item)
    print(p1.next)
    print('-' * 50)
    #创建链表
    linked_list = SingleLinkedList(p1)
    print(linked_list.head)
    print('-' * 50)
    # 判断链表是否为空
    print(linked_list.is_empty())
    print('-' * 50)
    #打印链表的长度
    print(linked_list.length())
    print('-' * 50)
    #打印链表内容
    linked_list.travel()
    print('-' * 50)
    #链表头部添加元素
    linked_list.add('华强')
    linked_list.travel()
    print('-' * 50)
    #链表尾部添加元素
    linked_list.append('刘华强')
    linked_list.travel()
    print('-' * 50)
    #在指定位置添加元素
    linked_list.insert(1, '刀哥')
    linked_list.travel()
    print('-' * 50)
    #删除元素
    linked_list.remove('强子')
    linked_list.travel()

运行结果:

五、总结

        python中实现模拟单链表还是比较简单的,文章如果有写的不对的或者写的不好的,欢迎大家指正。

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值