数据结构-链表-单链表(python)

一、单链表定义

以下为自己总结
链表中有多个节点,节点中存有数据、下个节点的地址,如果没有下个节点,则地址为空
链表如果要查看下一个节点,只能从节点存储的地址访问下一个节点,相当于python中的线性代码,只能从上往下运行,节点类似,只能从头开始,不能从中间、末尾开始
节点:
在这里插入图片描述
链表形式:
在这里插入图片描述

class Node:
    def __init__(self, val):
        # val 数据
        self.val = val
        # next 指指向下个节点的地址
        self.next = None

单链表的操作

下面图中的p都指游标

1. 创建一个单链表类

class SingleLinkList:
    def __init__(self, node: Node = None):
        self.__head = node

定义链表最初指向的地址:self.__head,默认为None ,文章后面用head表示

2. 判断链表是否为空

返回布尔值

    def is_empty(self) -> bool:
        return self.__head is None

链表内有节点,则返回False,为空链表,则返回True

3. 返回链表长度

定义长度变量为0
定义一个游标cur代表指向链表的位置
当游标目前不为空,则cur=cur.next,游标指向下一个节点,长度+1
为空后,说明已经是最后一个节点
最后返回长度count

    def length(self) -> int:
        count = 0
        cur = self.__head
        while cur:	
            cur = cur.next
            count += 1
        return count

4. 遍历整个链表

既然都能获取链表长度,那么也可以遍历链表了

    def travel_yield(self) -> Iterator:
        cur = self.__head
        while cur:
            yield cur.val
            cur = cur.next

5. 在链表头部添加数据

开始的时候,p的位置在链表的第一个节点,要在在第一个节点之前插入,

  1. 先把添加的数据定义node=Node(val),
  2. 然后node指向链表的第一个地址,即p:node.next = self.__head
  3. 再把p指向node:self.__head = node

在这里插入图片描述

    def add(self, val) -> None:
        node = Node(val)
        node.next = self.__head
        self.__head = node

6. 链表尾部添加数据

  1. 定义节点:node = Node(val)
  2. 插入尾部,有两种情况,一种是链表为空,另一种是已经有链表
    2.1 链表不为空
    创建一个游标cur,当cur.next不为空时cur = cur.next,为空则说明这是最后一个节点
    然后定义cur.next = node
    2.2 链表为空
    空链表,则直接指向node

代码如下

    def append(self, val) -> None:
        node = Node(val)
        if not self.is_empty():
            cur = self.__head
            while cur.next:
                cur = cur.next
            cur.next = node
        else:
            self.__head = node

7. 在指定位置添加元素

在指定位置添加元素需要传入添加元素的位置,即下标index,以及添加的数据val,有三种情况需要考虑

  1. index比链表长度大,以及index小于0
    此时需要处理并报错
  2. index为0
    即相当于在链表头部添加元素
  3. index等于链表长度
    即相当于在链表尾部添加元素
  4. index在链表中间

下方讲述的是情况4:
假设index=5

  1. 先定义节点:node = Node(val),游标、节点个数count,可以理解为游标位置的下标
  2. 因为游标如果移动到了5的位置,那么,就无法操作下标4,
    因此,移动游标的循环条件应该为count<index-1
  3. 当移动到4后node.next指向原下标5的位置,即node.next = cur.next
  4. 之后再把cur.next指向node
    链表中间部分
    def insert(self, index: int, val) -> None:
        length = self.length()
        if index < 0 or index > length:
            raise IndexError('超出链表长度范围')
        elif index == 0:
            self.add(val)
        elif index == length:
            self.append(val)
        else:
            node = Node(val)
            count = 0
            cur = self.__head
            while count < index - 1:
                count += 1
                cur = cur.next
            node.next = cur.next
            cur.next = node

8. 删除链表中节点

节点位置有三中地方

  1. 链表开头
  2. 链表中间
  3. 链表尾部
    有两种方法删除节点,第一种是创建一个游标,第二种是创建两个游标

8.1 创建一个游标删除节点

  1. 删除节点在链表开头
    如果head.val等于val,那么就说明,删除节点是在链表开头
    那么直接使head指向cur.next即可
  2. 删除节点在链表中间
    利用cur.next.val和val对比,将游标移动到要删除节点的前一个位置
    cur.next指向cur.next.next(当前游标位置的下下一个节点)
    在这里插入图片描述
  3. 删除节点在链表尾部
    链表尾部和链表中间一致,cur.next指向了要删除的节点,cur.next.next指向了要删除节点的后面,即尾部,那么指向的就是None

代码如下

    def remove(self, val) -> None:
        cur = self.__head
        if self.__head.val == val:
            self.__head = cur.next
        else:
            while cur.next:
                if cur.next.val == val:
                    if cur != self.__head:
                        cur.next = cur.next.next
                    else:
                        self.__head = cur.next
                    break
                else:
                    cur = cur.next

8.2 创建两个游标删除节点

创建两个游标cur§,pre(p1),其中,pre=None

  1. 删除节点在链表中间
    两个游标位置如图:
    在这里插入图片描述
    当cur.val 不等于val时,pre.next指向cur,cur指向cur.next
  2. 删除节点在链表头部
    当cur.val 等于val时,如果cur等于head,那么,head就指向cur.next即可
  3. 删除节点在链表尾部
    链表尾部和链表中间一致,pre.next指向了要删除的节点,cur.next指向了尾部的指向地址None,那么pre.next=cur.next

代码如下:

        cur = self.__head
        pre = None
        while cur:
            if cur.val == val:
                if cur != self.__head:
                    pre.next = cur.next
                else:
                    self.__head = cur.next
                break
            else:
                pre = cur
                cur = cur.next

三、整体代码

class Node:
    def __init__(self, val):
        self.val = val
        self.next = None


class SingleLinkList:
    def __init__(self, node: Node = None):
        self.__head = node

    def is_empty(self) -> bool:
        return self.__head is None

    def length(self) -> int:
        count = 0
        cur = self.__head
        while cur:
            cur = cur.next
            count += 1
        return count

    def travel_yield(self) -> Iterator:
        cur = self.__head
        while cur:
            yield cur.val
            cur = cur.next

    def add(self, val) -> None:
        node = Node(val)
        node.next = self.__head
        self.__head = node

    def append(self, val) -> None:
        node = Node(val)
        if not self.is_empty():
            cur = self.__head
            while cur.next:
                cur = cur.next
            cur.next = node
        else:
            self.__head = node

    def insert(self, index: int, val) -> None:
        length = self.length()
        if index < 0 or index > length:
            raise IndexError('超出链表长度范围')
        elif index == 0:
            self.add(val)
        elif index == length:
            self.append(val)
        else:
            node = Node(val)
            count = 0
            cur = self.__head
            while count < index - 1:
                count += 1
                cur = cur.next
            node.next = cur.next
            cur.next = node

    def remove(self, val) -> None:
        cur = self.__head
        pre = None
        while cur:
            if cur.val == val:
                if cur != self.__head:
                    pre.next = cur.next
                else:
                    self.__head = cur.next
                break
            else:
                pre = cur
                cur = cur.next
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值