Python | 四、链表

为什么需要链表

  • 在Python中,引入链表这一结构没有像C++等语言那样有很多好处,因为Python里的列表和字符串结构已经十分灵活且大小可变。Python中链表仍保留的好处如下:
    • 列表、字符串等结构是连续存储的,因此如果有一块较小的内存区域,这些数据结构将无法充分利用该内存空间,只能另寻大块的连续空间进行存储,这就导致了内存浪费
    • 面对数据量不固定、需要经常增加和删除数据同时对数据查询次数较少的场景,链表的时间复杂度性能更好(有关链表的性能分析见下,有关时间复杂度的内容见我的另一篇文章)

链表基本定义

  • 链表中的每一个节点(元素)都由两部分构成,data(数据域)和next(指针域),其中data存储当前节点的数据内容,next存储下一节点的地址信息
  • 链表中的第一个节点称为头结点headnode,最后一个节点的next为空(None)
    • Python | 四、链表_第1张图片
  • 链表的【存储方式】:链表在内存中不是连续存储的,通过节点的指针域链接,而每个节点具体分配到什么地址视具体的存储方式视操作系统的内存管理而定。如下图链表起始节点为2,终止节点为7,各个节点分布在内存的不同地址空间上,通过指针串联在一起
    • Python | 四、链表_第2张图片

其它链表类型

  • 前面所提到的链表为基础的单链表,下面介绍几种其它链表类型
  • 【双链表】,顾名思义,双链表就是双向链表,即每个节点既存储了上一个节点的地址,又存储了下一个节点的地址
    • 双链表头节点所存储的上一节点地址为空(None)
    • Python | 四、链表_第3张图片
  • 【循环链表】,即首尾相连的链表,此时链表里最后一个节点存储的地址为首节点的地址
    • 循环链表可以用来解决约瑟夫环的问题
    • Python | 四、链表_第4张图片

自定义链表类

  • 首先自定义节点类(有关类以及面向对象的内容见我下一篇博文)
  class ListNode:
      def __init__(self, data):
          self.data = data
          self.next = None
  • Python中自定义链表类,链表类的属性一般只包含头节点和链表长度,方法一般包括插入节点、打印节点等
class LinkList:
    def __init__(self):
        self.head_node = None
        self.length = 0
    def insert(self, data):
    	self.length += 1
    	new_node = ListNode(data)
    	if self.head_node is None:
    		self.head_node = new_node
    		return self.head_node
   		current_node = self.head_node
   		while current_node.next is not None:
   			current_node = current_node.next
   		current_node.next = new_node
   		return new_node
	def print_link_list(self):
		current_node = self.head_node
		while current_node is not None:
			print(current_node.data, end=' ')
			current_node = current_node.next
		print()

Python | 四、链表_第5张图片

链表的操作

  • 删除某一节点:在Python中,只需要直接把当前节点的next值赋给上一节点的next即可,使得上一节点重定向到下一节点,而不需要对当前删除节点进行内存释放,因为Python有自己的内存回收机制
    • Python | 四、链表_第6张图片
  • 添加某一节点:只需要把所添加位置上一节点的next赋值给所添加节点的next,并把所添加节点的地址赋值给上一节点即可
    • Python | 四、链表_第7张图片

链表的性能分析

  • Python | 四、链表_第8张图片
  • 有关时间复杂度的内容见我的另一篇文章

你可能感兴趣的:(Python基础,链表,数据结构,python)