python 实现单链表的基础操作:插入、删除、遍历、获取元素等

回顾一下单链表的知识,并用python实现单链表的基础操作:插入,删除,遍历,判空,清空链表,求长度, 获取元素,判断元素是否存在等。

链表通过指针将零散的内存块连接在一起,链表的每个节点存储有该节点的值和下一个节点的地址。

链表的第一个节点为基节点,最后一个节点是尾节点。头节点记录了链表的基地址,最后一个节点的指针指向None。

链表的插入,删除操作的时间复杂度都是O(1), 单链表的遍历时间复杂度是O(n)。

在这里插入图片描述

定义链表的同时也要定义链表节点Node,节点存储值item和指针_next, 也可理解为引用,指向的是下一个节点的地址。

看了下王争老师的代码,对链表的插入和删除操作考虑都比较全面。

动手写了一遍之后,发现根据某个值删除节点的操作有点意思。

因为不知道这个值在哪里,所以需要挨个遍历链表,删除该节点时,将删除的节点的值赋值为下一个节点的值,然后删除下一个节点。

就像是如果要我死,就让我变成A,然后杀了A的原主。

我没有了,而A还活着。但其实我就是A。

    def delete_by_value(self, value: int):
        if not self.head or not value:
            return
        fake_head = Node(-1)
        fake_head.next = self.head
        prev, current = fake_head, self.head
        while current:
            if current.item != value:
                prev.next = current
                prev = prev.next
            current = current.next

        if prev.next:  # current.item == value
            prev.next = prev.next.next
        self.head = fake_head.next
全部代码
class Node:
    """链表节点"""

    def __init__(self, item: int, next=None):
        self.item = item
        self.next = next


class LinkedList:
    """链表"""

    def __init__(self):
        self.head = None

    def find_by_value(self, value: int):
        # 根据值查找节点
        p = self.head
        while p and p.item != value:
            p = p.next
        return p

    def find_by_index(self, position: int):
        # 根据索引位置查找节点,需要挨个遍历
        p = self.head
        index = 0
        while p and index != position:
            p = p.next
            index += 1
        return p

    def insert_value_to_head(self, value: int):
        node = Node(value)
        self.insert_node_to_head(node)

    def insert_node_to_head(self, node):
        if node:
            node.next = self.head
            self.head = node

    def insert_node_after(self, node, new_node):
        if not node or not new_node:
            return
        new_node.next = node.next
        node.next = new_node

    def insert_value_after(self, node, value):
        new_node = Node(value)
        self.insert_node_after(node, new_node)

    def insert_node_before(self, node, new_node):
        if not self.head or not node or not new_node:
            return

        if node == self.head:
            self.insert_node_to_head(new_node)
            return

        p = self.head
        while p and p.next != node:
            p = p.next

        if not p:
            return

        new_node.next = node
        p.next = new_node

    def insert_value_before(self, value: int, node):
        new_node = Node(value)
        self.insert_node_before(node, new_node)

    def delete_by_node(self, node):
    	# 删除某个节点
        if not self.head or not node:
            return

        # 不是最后一个节点,可以直接删除, 删除的复杂度为O(1)
        if node.next:
            node.item = node.next.item
            node.next = node.next.next

        p = self.head
        while p and p.next != node:
            p = p.next

        if not p:
            return

        p.next = node.next

    def delete_by_value(self, value: int):
    	# 删除某个值对应的节点
        if not self.head or not value:
            return
        fake_head = Node(-1)
        fake_head.next = self.head
        prev, current = fake_head, self.head
        while current:
            if current.item != value:
                prev.next = current
                prev = prev.next
            current = current.next

        if prev.next:  # current.item == value
            prev.next = prev.next.next
        self.head = fake_head.next

    def __repr__(self):
    	# 打印链表,重写repr或者str函数
        a = []
        p = self.head
        while p:
            a.append(p.item)
            p = p.next
        return " ".join(map(str, a))


if __name__ == '__main__':
    l = LinkedList()
    for i in range(10):
        l.insert_value_to_head(i)

    node = l.find_by_value(5)
    l.insert_value_before(20, node)
    l.insert_value_after(node, 24)
    print(l)
    l.delete_by_value(4)
    print(l)

以下是一些基础代码,不知道为什么看代码有点幼稚。

判空

判断链表是否是空链表只需要判断头节点是否为None即可。

如果为None表示头节点没有指向下一个节点。

    def is_empty(self):
        """判断是否为空链表,头节点为None则是空"""
        return self._head is None
求链表长度

从头节点开始遍历,直到最后的空节点None。

    def length(self):
        """求链表的长度"""
        p = self._head
        count = 0
        while p:
            count += 1
            p = p._next
        return count
向链表尾部追加元素

如果链表是空链表,则该节点为头节点,否则依次遍历到最后一个值p,然后 p._next = node

    def append(self, item):
        """向链表尾部添加元素, 考虑是否是空链表"""
        node = Node(item)
        p = self._head
        if not p:
            self._head = node
        else:
            while p._next:
                p = p._next
            p._next = node
向链表头部插入元素

头插法。其实就是把该元素设置为头节点
在这里插入图片描述

    def add(self, item):
        """向链表头部插入元素"""
        node = Node(item)
        node._next = self._head
        self._head = node
向链表中插入元素

分为头插,尾插,中间插入

插入元素的核心是node._next = pre._next , pre._next = node, 先后次序一定要注意。先让待插入的node指向p._next, 再让p指向node
在这里插入图片描述

    def insert(self, position, item):
        """向链表中插入元素"""
        # 头插 or 尾插 or 中间插入
        if position <= 0:
            self.add(item)
        elif position >= self.length():
            self.append(item)
        else:
            pre = self._head
            count = 0
            while count < position - 1:
                count += 1
                pre = pre._next
            node = Node(item)
            node._next = pre._next
            pre._next = node
获取某位置的元素
    def get_item(self, position):
        """获取某位置的元素"""
        if position < 0 or position >= self.length():
            return None
        p = self._head
        count = 0
        while count != position:
            p = p._next
            count += 1
        return p.item
判断值是否存在
    def exixt_value(self, item):
        """某个值是否存在"""
        p = self._head
        while p:
            if p.item == item:
                return True
            else:
                p = p._next
        return False
删除元素

删除头节点一行代码即可。
其他位置的需要判断+遍历
在这里插入图片描述

    def remove(self, item):
        """删除元素"""
        p = self._head
        pre = None
        while p:
            if p.item == item:
                # 是否头节点
                if not pre:
                    self._head = p._next
                else:
                    pre._next = p._next
                    break
            else:
                pre = p
                p = p._next
清空链表
    def clear(self):
        """删除链表"""
        self._head = None
链表遍历
    def travel(self):
        """列表遍历"""
        p = self._head
        while p:
            print(p.item, end=" ")
            p = p._next
        print()
测试用例
if __name__ == '__main__':
    linklist = LinkList()
    linklist.append(2)
    linklist.append(3)
    linklist.append(4)
    linklist.append(5)
    print(linklist.length())  # 4
    linklist.travel()  # 2 3 4 5
    linklist.add(1)
    linklist.add(0)
    linklist.travel()   # 0 1 2 3 4 5
    linklist.insert(2, 8)
    linklist.insert(2, 9)
    linklist.travel()   # 0 1 9 8 2 3 4 5
    print(linklist.get_item(2), linklist.get_item(12), linklist.get_item(4))    # 9 None 2
    print(linklist.exixt_value(9), linklist.exixt_value(20))    # True False
    linklist.remove(9)
    linklist.remove(5)
    linklist.travel()   # 0 1 8 2 3 4
    linklist.clear()
    linklist.travel()  # 空
完整代码
"""
链表基本操作:创建空链表,删除链表,判断是否为空,添加元素,删除元素,遍历,定位,链表长度
"""


class Node:
    """链表节点初始化"""
    def __init__(self, item):
        self.item = item
        self._next = None


class LinkList:
    """链表及其相关操作"""
    def __init__(self):
        self._head = None

    def is_empty(self):
        """判断是否为空链表,头节点为None则是空"""
        return self._head is None

    def length(self):
        """求链表的长度"""
        p = self._head
        count = 0
        while p:
            count += 1
            p = p._next
        return count

    def append(self, item):
        """向链表尾部添加元素, 考虑是否是空链表"""
        node = Node(item)
        p = self._head
        if not p:
            self._head = node
        else:
            while p._next:
                p = p._next
            p._next = node

    def add(self, item):
        """向链表头部插入元素"""
        node = Node(item)
        node._next = self._head
        self._head = node

    def insert(self, position, item):
        """向链表中插入元素"""
        # 头插 or 尾插 or 中间插入
        if position <= 0:
            self.add(item)
        elif position >= self.length():
            self.append(item)
        else:
            pre = self._head
            count = 0
            while count < position - 1:
                count += 1
                pre = pre._next
            node = Node(item)
            node._next = pre._next
            pre._next = node

    def get_item(self, position):
        """获取某位置的元素"""
        if position < 0 or position >= self.length():
            return None
        p = self._head
        count = 0
        while count != position:
            p = p._next
            count += 1
        return p.item

    def exixt_value(self, item):
        """某个值是否存在"""
        p = self._head
        while p:
            if p.item == item:
                return True
            else:
                p = p._next
        return False

    def remove(self, item):
        """删除元素"""
        p = self._head
        pre = None
        while p:
            if p.item == item:
                # 是否头节点
                if not pre:
                    self._head = p._next
                else:
                    pre._next = p._next
                    break
            else:
                pre = p
                p = p._next

    def clear(self):
        """删除链表"""
        self._head = None

    def travel(self):
        """列表遍历"""
        p = self._head
        while p:
            print(p.item, end=" ")
            p = p._next
        print()


if __name__ == '__main__':
    linklist = LinkList()
    linklist.append(2)
    linklist.append(3)
    linklist.append(4)
    linklist.append(5)
    print(linklist.length())  # 4
    linklist.travel()  # 2 3 4 5
    linklist.add(1)
    linklist.add(0)
    linklist.travel()   # 0 1 2 3 4 5
    linklist.insert(2, 8)
    linklist.insert(2, 9)
    linklist.travel()   # 0 1 9 8 2 3 4 5
    print(linklist.get_item(2), linklist.get_item(12), linklist.get_item(4))    # 9 None 2
    print(linklist.exixt_value(9), linklist.exixt_value(20))    # True False
    linklist.remove(9)
    linklist.remove(5)
    linklist.travel()   # 0 1 8 2 3 4
    linklist.clear()
    linklist.travel()  # 空

  • 27
    点赞
  • 123
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值