关于Python实现树结构和链表结构的一点想法
Python由于内置的数据结构具有很高的灵活性,所以可以用很多种方式来构建树、图、链表等结构
1. 树的Python实现
- python自然可以使用class来创建Node结点类和Trie类,然后通过left和right属性保存Node结点来实现树
- Python也可以使用字典来嵌套生成树,字典的Key作为当前结点,字典的Value为子树。
- 但需要注意的是,字典的value是一个字典,那么这个value字典中可以有多个Key,那么每个Key之间是互相为兄弟关系的。
- 同理,如列表等数据结构,也可以通过嵌套来生成树
- 在使用字典创建树时,可以重复利用dict的方法setdefault(key,default),如果key存在,则返回value,若不存在,则插入key:default并返回default
--------------------------
- 比较有意思的是对于树而言,在哪里存他的数据会有很多的不同,对于不同场景酌情实现
- 假设是使用class实现的字母前缀树,那么可以把字母值保存在当前Node结点的value中,那么这样匹配一个单词的时候,需要遍历所有的子节点找到对应值是否存在,这样在某一层上就多花了k的时间(由于字典自带哈希,所以字典实现的前缀树查找会很快,是O(1)的时间)
- 也可以把字母值保存在连向子结点的连线上
- 由于字母前缀树每个结点最多只有26种取值,所以可以提前存一个初始化为26个None的列表,如果在b的位置有值,那么在第二个位置存子结点的Node,这样就实现了把字母值存在连向子结点的连线上。
- 同时,匹配一个单词的时候,直接来判断这个位置是None还是存在Node结点就可以直接找到下一个结点了,也是O(1)的时间,但是如果树很深,但是很窄的话,这样会浪费许多空间
- 所以针对不同的场景需求,可以自行选择存储数据的位置,有不同的效果。
利用字典实现树代码如下
#利用字典实现前缀树
trie = {}
# 建立字典实现的字母前缀树
for word in words:
cur = trie
for alpha in word:
cur=cur.setdefault(alpha,{})
2. 链表的Python实现
- python本身的列表已经很好用了,在python的标准库中没有链接列表的实现,如果需要大量插入和删除还是需要手动实现一下的,可以实现O(k)的增删查找复杂度
- 链表实现自然也可以用class来创建Node结点类和Trie类,在Trie类中创建head与tail的Node对象,就可以进行追踪了
- 如果需要O(1)的查找以及增删复杂度的链表,那么需要配合哈希与双向链表实现、那么在Trie类中还需要添加一个dict哈希来进行节点位置的追踪,key为Node节点的Key(Node节点属性有Key、value、next、pre),Value为该Node节点
#配合哈希与双向链表实现O(1)的查找以及增删复杂度
class Node:
def __init__(self,key,value):
self.key=key
self.value=value
self.next=None
self.pre=None
class LRUCache:
def __init__(self, capacity: int):
self.dic=dict()
self.capacity=capacity
self.size=0
self.head=Node(-1,-1)
self.tail=Node(-1,-1)
self.head.next=self.tail
self.tail.pre=self.head
def get(self, key: int) -> int:
if(key in self.dic):
new_node = Node(key, self.dic[key].value)
# 删除旧节点
del_node = self.dic[key]
del_node.pre.next = del_node.next
del_node.next.pre = del_node.pre
# 添加新节点到头部
new_node.pre = self.head
new_node.next = self.head.next
self.head.next.pre = new_node
self.head.next = new_node
self.dic[key]=new_node
return self.dic[key].value
else:
return -1
def put(self, key: int, value: int) -> None:
new_node = Node(key, value)
# 添加新节点到头部
new_node.pre = self.head
new_node.next = self.head.next
self.head.next.pre = new_node
self.head.next = new_node
if(key in self.dic):
del_node=self.dic[key]
del_node.pre.next=del_node.next
del_node.next.pre=del_node.pre
else:
# 如果key不在链表中,才考虑删去尾元素或者更改size
if(self.size==self.capacity):
# 如果满了,要删去尾部节点
self.dic.pop(self.tail.pre.key)
self.tail.pre.pre.next=self.tail
self.tail.pre=self.tail.pre.pre
else:
self.size+=1
self.dic[key] = new_node