关于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