算法运用场景
无限级分类树状结构的应用场景很多,例如后端研发需要把用户相关的权限读取出来并生成树状结构,前端研发拿到树状结构之后,可以按照结构展示用户有权限访问的栏目,再例如网页上的栏目分级:
数据存储信息如下
[
{"id":1, "name":"电器","parent":0},
{"id":2, "name":"水果","parent":0},
{"id":3, "name":"家用电器","parent":1},
{"id":4, "name":"电吹风","parent":3},
{"id":5, "name":"电风扇","parent":3},
{"id":6, "name":"台灯","parent":3},
{"id":7, "name":"商用电器","parent":1},
{"id":8, "name":"大型电热锅","parent":7},
]
算法的实现
字段parent记录的是此条目的父编号,例如电吹风的父编号是3,即电吹风属于家用电器,而家用电器的父编号是1,即家用电器属于电器类产品,电吹风条目跟电器条目并无直接的标识进行关联,但需要用树状结构来表明,电器<-家用电器<-电吹风的关系 通过parent 寻找父编号,并建立关联关系的操作实际上是循环往复的,直到找完所有的节点,这跟递归算法非常契合
def generate_tree(source, parent):
tree = []
for item in source:
if item["parent"] == parent:
item["child"] = generate_tree(source, item["id"])
tree.append(item)
return tree
只需要将数据库中存储的信息传递给generate_tree 函数即可,这段递归代码在往复循环的过程中通过parent来寻找子节点,找到子节点后,将其添加到树中,完整代码如下:
import json
def generate_tree(source, parent):
tree = []
for item in source:
if item["parent"] == parent:
item["child"] = generate_tree(source, item["id"])
tree.append(item)
return tree
if __name__ == "__main__":
permission_source = [
{"id":1, "name":"电器","parent":0},
{"id":2, "name":"水果","parent":0},
{"id":3, "name":"家用电器","parent":1},
{"id":4, "name":"电吹风","parent":3},
{"id":5, "name":"电风扇","parent":3},
{"id":6, "name":"台灯","parent":3},
{"id":7, "name":"商用电器","parent":1},
{"id":8, "name":"大型电热锅","parent":7},
]
permission_tree = generate_tree(permission_source, 0)
print(json.dumps(permission_tree, ensure_ascii=False))
得到的结果是这样的
[{
"id": 1,
"name": "电器",
"parent": 0,
"child": [{
"id": 3,
"name": "家用电器",
"parent": 1,
"child": [{
"id": 4,
"name": "电吹风",
"parent": 3,
"child": []
}, {
"id": 5,
"name": "电风扇",
"parent": 3,
"child": []
}, {
"id": 6,
"name": "台灯",
"parent": 3,
"child": []
}]
}, {
"id": 7,
"name": "商用电器",
"parent": 1,
"child": [{
"id": 8,
"name": "大型电热锅",
"parent": 7,
"child": []
}]
}]
}, {
"id": 2,
"name": "水果",
"parent": 0,
"child": []
}]
使用缓存算法来进行优化
递归算法中有很多重复的计算,这些计算不仅占用额外资源,还会降低函数执行效率,因此需要对递归算法进行优化 基本思路是每次找到节点关系后将此条目的编号添加到一个列表中缓存起来,代表此条目找到节点关系,当往复执行函数时再遇到此条目可以跳过,代码改动很简单
import json
def generate_tree(source, parent, cache=[]):
tree = []
for item in source:
if item['id'] in cache:
continue
if item["parent"] == parent:
cache.append(item['id'])
item["child"] = generate_tree(source, item["id"], cache)
tree.append(item)
return tree
if __name__ == "__main__":
permission_source = [
{"id":1, "name":"电器","parent":0},
{"id":2, "name":"水果","parent":0},
{"id":3, "name":"家用电器","parent":1},
{"id":4, "name":"电吹风","parent":3},
{"id":5, "name":"电风扇","parent":3},
{"id":6, "name":"台灯","parent":3},
{"id":7, "name":"商用电器","parent":1},
{"id":8, "name":"大型电热锅","parent":7},
]
permission_tree = generate_tree(permission_source, 0)
print(json.dumps(permission_tree, ensure_ascii=False))