Python-单链表结构上的操作

定义一个单链表节点类

class Node(object):
    def __init__(self, data, next=None):
        self.data = data
        self.next = next
  • 遍历

    使用一个临时的指针变量。这个变量先初始化为链表结构的head指针,然后控制一个循环。如下所示:

    probe = head
    while probe != None:
        <use or modify probe.data>
        probe = probe.next
    
  • 搜索

    一个链表结构的顺序搜索和遍历是类似的,因为也必须从第1节点开始并且沿着链接直到遇到哨兵。然而,在这个例子中,会出现两个哨兵:

      1. 空链接,表明不再有要检查的数据。
      2.  等于目标项的一个数据项,表明一次成功的搜索。
    

    如下是搜索一个给定项的形式:

    probe = head
    while probe != None and targetItem != probe.data:
    	probe = probe.next
    if probe != None:
    	<targetItem has been found>
    else:
    	<targetItem is not in the linked structure>
    

    平均情况下,对于单链表结构的顺序搜索是线性的。
    访问一个链表结构中的第 i 项,也是一次顺序搜索操作。这是因为,必须从第1个节点开始统计链接的数目,直到遇到第 i 个节点。可以假设 0 <= i < n ,其中 n 是链表结构中的节点数目。如下是访问第 i 项的代码:

    # Assumes 0 <= index < n
    probe = head
    while index > 0:
    	probe = probe.next
    	index -= 1
    return probe.data
    

    和数组不同,链表结构并不支持随机访问。

  • 替换

    单链表结构中的替换操作也利用了遍历模式。在链表结构中搜索一个给定项或一个给定位置,并且用新的项替换该项。
    第一个操作,即替换一个给定的项,并不需要假设目标项在链表结构中。如果目标项不存在,那就不会发生替换,并且该操作返回False。如果目标项存在,新的项会替换它,并且该操作返回True。如下是该操作的形式:

    probe = head
    while probe != None and targetItem != probe.data:
    	probe = probe.next
    if probe != None:
    	probe.data = newItem
    	return True
    else:
    	return False
    

    还有一个替换第 i 项的操作,假设 0 <= i < n ,其形式如下:

    # Assumes 0 <= index < n
    probe = head
    while index > 0:
    	probe = probe.next
    	index -= 1
    probe.data = newItem
    

    两种替换操作在平均情况下都是线性的。

  • 在开始处插入

    在结构的开始处插入一项。其形式如下:
    head = Node(newItem, head)
    在第一种情况下,head指针是None,因此,向结构中插入了第1项。在第2中情况下,将第2项插入到了同一结构的开头处。
    在这里插入图片描述
    注意在第2种情况中,不需要复制数据并向下移动数据,并且并不需要额外的内存。这意味着,在一个链表结构的开始处插入数据,时间和内存都是常数,这与数组的相应操作有所不同。

  • 在末尾插入

    对于单链表结构来说,在末尾插入一项必须考虑如下两种情况:

     1. head指针为None,此时,将head指针设置为新的节点。
     2. head指针不为None,此时,代码将搜索最后一个节点,并将其next指针指向新的节点。
    

    第2种情况又回到了遍历模式。其形式如下:

    newNode = Node(newItem)
    if head is None:
    	head = newNode
    else:
    	probe = head
    	while probe.next != None:
    		probe = probe.next
    	probe.next = newNode
    
  • 从开始处删除

    在这种类型的操作中,通常可以假设结构中至少有一个节点。这个操作返回删除项。其形式如下:

    removedItem = head.data
    head = head.next
    return removedItem
    

    该操作使用的时间和内存都是常数的。

  • 从末尾删除

    对于单链表结构来说,从末尾删除的操作假设结构中至少有一个节点。需要考虑如下的两种情况:

     1. 只有一个节点。head指针设置为None。
     2. 在最后一个节点之前有一个节点。代码搜索倒数第2个节点并将其next指针设置为None。
    

    在这两种情况下,代码都返回了所删除的节点所包含的数据项。如下:

    removedItem = head.data
    if head.next is None:
    	head = None
    else:
    	probe = head
    	while probe.next.next != None:
    		probe = probe.next
    	removedItem = probe.next.data
    	probe.next = None
    return removedItem
    

    该操作在时间上和内存上都是线性的。

  • 在任何位置插入

    要在 i 位置插入,必须首先找到位置为 i-1 (如果 i < n )或 n-1 (如果 i >= n )的节点。然后,考虑如下两种情况:

     1. 该节点的next指针为None。这意味着, i >= n,因此,应该将新的项放在链表结构的末尾。
     2. 该节点的next指针不为None。这意味着, 0 < i < n ,因此,必须将新的项放在位于 i - 1和 i 的节点之间。
    

    和搜索第 i 项相同,插入操作必须计数节点,直到到达了想要的位置。然而,由于目标索引可能会大于或等于节点的数目,因此在搜索中,必须小心避免超出链表结构的末尾。为了解决这个问题,循环有一个额外的条件,就是测试当前节点的next指针,看看这个节点是否是最后一个节点。形式如下:

    if head is None or index <= 0:
    	head = Node(newItem, head)
    else:
    	probe = head
    	while index > 1 and probe.next != None:
    		probe = probe.next
    		index -= 1
    	probe.next = Node(newItem, probe.next)
    

    和使用了遍历模式的单链表结构操作一样,这个操作的性能也是线性的。然而,它使用的内存是常数的。

  • 从任意位置删除

    从一个链表结构中删除第 i 个项,具有一下3种情况:

     1. i <= 0——使用删除第1项的代码。
     2. 0 < i < n——搜索位于 i - 1位置的节点,删除其后面的节点。
     3. i >= n——删除最后一个节点。
    

    假设链表结构至少有1项。这个模式类似于插入节点所使用的模式,必须保证不会超过链表结构的末尾。换言之,必须允许probe指针不会超过链表结构的倒数第2个节点。形式如下:

    if index <= 0 or head.next is None:
    	removedItem = head.data
    	return removedItem
    else:
    	probe = head
    	while index > 1 and probe.next.next != None:
    		probe = probe.next
    		index -= 1
    	removedItem = probe.next.data
    	probe.next = probe.next.next
    	return removedItem
    
  • 复杂度权衡:时间、空间和单链表结构

操作运行时间
在第 i 个位置访问O(n),平均情况
在第 i 个位置替换O(n),平均情况
在开始处插入O(1),最好情况和最差情况
从开始处删除O(1),最好情况和最差情况
在第 i 个位置插入O(n),平均情况
从第 i 个位置删除O(n),平均情况
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值