03数据结构与算法_单链表_Python实现

本文对比了链式结构与线性结构的特点,详细阐述了链式结构在内存分配上的灵活性及其操作上的优势与劣势。同时,提供了单链表的Python实现,包括节点定义、链表基本操作如追加、插入、遍历、删除等,以及测试用例验证其正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

'''
链式与线性结构的区别:
    线性————内存连续、下标访问;
    链式————内存不连续、无下标,追加时很方便,寻找的话很麻烦需要遍历。
'''

#定义节点(具有value和next属性,值和指针)
class Node(object):
    def __init__(self,value=None,next=None):
        self.value = value
        self.next = next


#定义单链表
class LinkedList(object):
    def __init__(self,max_size=None):
        self.max_size = max_size
        self.root = Node()
        self.length = 0
        self.tail_node = None

    def __len__(self):
        return self.length

    def append(self,value):
        if self.max_size is not None and len(self) > self.max_size:
            raise Exception("Full")
        node = Node(value)
        tail_node = self.tail_node
        if tail_node is None:   #只有根节点
            self.root.next = node
        else:
            tail_node.next = node
        self.tail_node = node
        self.length += 1

    def append_left(self,value):
        """插入到root节点的后边"""
        head_node = self.root.next  #构造头结点
        node = Node(value)
        self.root.next = node
        node.next = head_node   #把当前节点的下一个节点再指向头结点
        self.length += 1

    def iter_node(self):
        """遍历从head节点到tail节点"""
        curr_node = self.root.next
        while curr_node is not self.tail_node:
            #只要不是尾节点就yield当前节点
            yield curr_node
            curr_node = curr_node.next  #更新成下一个节点
        yield curr_node

    def __iter__(self):
        for node in self.iter_node():
            yield node.value

    def remove(self,value):     #O(n)
        """删除包含值的一个节点,将其前一个节点的next指向被查询节点的下一个即可"""
        prev_node = self.root
        curr_node = self.root.next
        for curr_node in self.iter_node():
            if curr_node.value == value:
                #查找到时,当前节点指向当前节点的下一个节点
                prev_node.next = curr_node.next
                if curr_node is self.tail_node:
                    self.tail_node = prev_node      #注意更新tail_node
                del curr_node
                self.length -= 1
                return 1
            else:
                prev_node = curr_node       #更新prev_node
        return -1

    def find(self,value):   #O(n)
        index = 0
        for node in self.iter_node():
            if node.value == value:
                return index
            index += 1
        return -1


    def pop_left(self):     #O(1)
        if self.root.next is None:
            raise Exception("Pop from empty LinkedList.")
        head_node = self.root.next
        self.root.next = head_node.next     #头结点指向头结点的下一个节点
        self.length -= 1
        value = head_node.value
        del head_node
        return value


    def clear(self):
        for node in self.iter_node():
            del node
        self.root.next = None
        self.length = 0


def test_linkedNode():
    ll = LinkedList()

    ll.append(0)
    ll.append(1)
    ll.append(2)
    ll.append(3)

    assert len(ll) == 4
    assert ll.find(2) == 2

    ll.remove(0)
    assert len(ll) == 3

    ll.append_left(0)
    assert list(ll) == [0,1,2,3]



test_linkedNode()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值