在Python中使用关联列表数据结构

99 阅读4分钟

在Python中使用关联列表数据结构

在掌握了Python中所有的线性数据结构之后,我们几乎已经到了这个系列的终点。最后,我们有一个最复杂的线性数据结构,即强大的**关联列表。**😏

Thanos Meme, Linked List
正如备忘录中所说的,头部是链接列表中最不可或缺的部分!

好吧,关联列表并不像你想象的那么复杂。不过,它的功能非常强大。

关于Python中不同类型的数据结构的更多背景,请查看下面的文章。

关联列表。简介

链接列表是一种线性数据结构。它们是一个数据序列,通过链接或指针 连接在一起。

链接列表是一个节点链,通过链接连接在一起。每个节点(链接列表的基本块)都包含以下字段。

  • 数据-> 要存储在节点中的项目。
  • 下一个-> 到下一个节点的链接或引用

Node, Linked List
在一个链接列表中,第一个节点被称为,最后一个节点是由下一个指向空值的条件决定的。

Null, Linked List

链接列表的用途

  • 由于其动态大小的分配和插入/删除的便利性,链接列表被应用于很多的使用案例。
  • 它们被用来实现很多复杂的数据结构,比如图中的邻接列表
  • 它们被用于操作系统中的生命周期管理
  • 音乐应用中的播放列表是用双链表实现的。
  • 区块链,一种用于加密货币和分类账的复杂数据结构,其核心是使用一个链接列表。

实现关联列表

有两种主要类型的关联列表。

  • 单一关联列表
  • 双重链接列表

单一关联列表

在下面的例子中,我们将用Python从头开始实现一个单链表。这包含以下方法。

  • ll.search(head, data)-> 在链接列表中搜索给定的元素。
  • ll.print_list()-> 打印链接列表。
  • ll.size()-> 返回链接列表的长度。
  • ll.insert(ele)-> 将给定的节点插入到链表中。
  • ll.delete(data)-> 从链表中删除给定元素。
class Node(object):
	def __init__(self, data):
		self.data = data
		self.next = None

# Class to create a Linked List
class LinkedList(object):
	def __init__(self, head=None):
		self.head = head

	# Search an element and print its index
	def search(self, head, data, index):
		if head.data == data:
			print (index)
		else:
			# Make recursive calls
			if head.next:
				return self.search(head.next, data, index+1)
			else:
				raise ValueError("Node not in linked list")

	# Print the linked list
	def print_list(self):
		if self.head == None:
			raise ValueError("List is empty")

		current = self.head 
		while(current):
			print (current.data, end="  ")
			current = current.next
		print ('\n')

	# Find length of Linked List
	def size(self):
		if self.head == None:
			return 0

		size = 0
		current = self.head
		while(current):
			size += 1
			current = current.next

		return size

	# Insert a node in a linked list
	def insert(self, data):
		node = Node(data)
		if not self.head:
			self.head = node
		else:
			node.next = self.head
			self.head = node

	# Delete a node in a linked list
	def delete(self, data):
		if not self.head:
			return
		
		temp = self.head
		
		# Check if head node is to be deleted
		if head.data == data:
			head = temp.next
			print ("Deleted node is " + str(head.data))
			return

		while(temp.next):
			if (temp.next.data == data):
				print ("Node deleted is " + str(temp.next.data))
				temp.next = temp.next.next
				return
			temp = temp.next
		print ("Node not found")
		return

双链表

一个双链表与单链表相似。它的不同之处在于,它还包含一个到前一个节点的链接。

Doubly Linked List
我们为双链表的数据结构实现以下方法。

  • dll.addNodeLast(x)-> 在链表的右端增加一个节点。
  • dll.insertNode(pos, x)-> 在指定的位置增加一个节点。
  • dll.removeNode(x)-> 移除指定的节点。
  • dll.showReverse()-> 反向打印链表。
  • dll.show()-> 打印链表。
class Node:
    def __init__(self, val):
        self.value = val
        self.next = None
        self.prev = None
    
class DoublyList:
    def __init__(self, val):
        self.head = Node(val)
        self.tail = self.head

    def addNodeLast(self, val):
        current = self.head
        while current.next != None:
            current = current.next
        newNode = Node(val)
        current.next = newNode
        newNode.prev = current
        self.tail = newNode

    def insertNode(self, val, newVal):
        if self.tail.value == val:
            self.addNodeLast(newVal)
        elif self.head.value == val:
            newNode = Node(newVal)
            newNode.next = self.head.next
            newNode.prev = self.head
            newNode.next.prev = newNode
            self.head.next = newNode
        else:
            current = self.head.next
            while current.value != val:
                current = current.next
            newNode = Node(newVal)
            newNode.next = current.next
            newNode.next.prev = newNode 
            newNode.prev = current
            current.next = newNode

    def removeNode(self, val):
        if self.head.value == val:
            self.head = self.head.next
            self.head.prev = None
        elif self.tail.value == val:
            self.tail = self.tail.prev
            self.tail.next = None
        else:
            current = self.head.next
            while current.value != val:
                current = current.next
            current.prev.next = current.next
            current.next.prev = current.prev

    def showReverse(self):
        current = self.tail
        while current != None:
            print(current.value)
            current = current.prev

    def show(self):
        current = self.head
        while current != None:
            print(current.value)
            current = current.next

练习关联列表

首先,尝试实现如上所示的关联列表,然后尝试运行它们。一旦你掌握了实现方法,就可以尝试给定的问题集来掌握关联列表。

总结

关联列表可能有点吓人,但是一旦你理解了它们,你就会发现理解树、图和其他类似的数据结构也很容易了恭喜你,在本系列文章结束时,你已经掌握了线性数据结构。