python 递归

该代码实现从城市列表数据递归构建城市树结构,并根据指定的城市ID筛选出包含选中节点的子树。城市数据包含省份和下属城市的层级关系,通过`get_tree`函数生成全树,`get_selected_tree`函数则用于获取包含特定城市的子树。

1)递归将列表转化成树

2)递归获取选中节点树

# 城市列表
data = [
    {"id":1,"name":"浙江","upperid":None},
    {"id":2,"name":"江苏","upperid":None},
    {"id":3,"name":"福建","upperid":None},
    {"id":11,"name":"杭州","upperid":1},
    {"id":12,"name":"嘉兴","upperid":1},
    {"id":21,"name":"苏州","upperid":2},
    {"id":22,"name":"无锡","upperid":2},
    {"id":31,"name":"福州","upperid":3},
    {"id":32,"name":"厦门","upperid":3},
    {"id":111,"name":"萧山","upperid":11},
    {"id":112,"name":"临安","upperid":11},
    {"id":121,"name":"嘉善","upperid":12},
    {"id":122,"name":"桐乡","upperid":12},
    {"id":211,"name":"吴江","upperid":21},
    {"id":212,"name":"常熟","upperid":21}
]

 
# 根据城市列表,递归获取城市树
def get_tree(data):
    tree_data=[]
    for node in [node for node in data if node['upperid'] == None]:
        node['path']=[]
        node['path'].append(node['id'])
        node['children']=[]
        tree_data.append(node)
        get_children(node,data)
    return tree_data
 
def get_children(upper_node,data):
    res = [node for node in data if node['upperid'] == upper_node['id']]
    if len(res)>0:
        for node in res:
            node['path']=[]
            node['path'].extend(upper_node['path'])
            node['path'].append(node['id'])
            node['children']=[]
            upper_node['children'].append(node)
            get_children(node,data)

# 获取选中节点树(包括父节点)
def get_selected_tree(tree,ids):
    new_tree=[]
    for root_node in tree:
        is_keep=is_node_keep(root_node,ids)
        if is_keep==True:
            new_tree.append(root_node)
    return new_tree

def is_node_keep(node,ids):
    is_keep=False
    if node['id'] in ids:
        is_keep=True
    if len(node['children']):
        new_children=[]
        for child_node in node['children']:
            is_child_keep=is_node_keep(child_node,ids)
            if is_child_keep==True:
                new_children.append(child_node)
        if len(new_children)>0:
            is_keep=True
        node['children']=new_children
    return is_keep

# 调用递归方法
print('城市树结构')
tree=get_tree(data)
print(tree)
print('选中城市(杭州、嘉善、吴江)')
ids=[11, 121, 211]
new_tree=get_selected_tree(tree,ids)
print(new_tree)

全树json效果

[{
	"id": 1,
	"name": "浙江",
	"upperid": "",
	"path": [1],
	"children": [{
		"id": 11,
		"name": "杭州",
		"upperid": 1,
		"path": [1, 11],
		"children": [{
			"id": 111,
			"name": "萧山",
			"upperid": 11,
			"path": [1, 11, 111],
			"children": []
		}, {
			"id": 112,
			"name": "临安",
			"upperid": 11,
			"path": [1, 11, 112],
			"children": []
		}]
	}, {
		"id": 12,
		"name": "嘉兴",
		"upperid": 1,
		"path": [1, 12],
		"children": [{
			"id": 121,
			"name": "嘉善",
			"upperid": 12,
			"path": [1, 12, 121],
			"children": []
		}, {
			"id": 122,
			"name": "桐乡",
			"upperid": 12,
			"path": [1, 12,
				122
			],
			"children": []
		}]
	}]
}, {
	"id": 2,
	"name": "江苏",
	"upperid": "",
	"path": [2],
	"children": [{
		"id": 21,
		"name": "苏州",
		"upperid": 2,
		"path": [2, 21],
		"children": [{
			"id": 211,
			"name": "吴江",
			"upperid": 21,
			"path": [2, 21, 211],
			"children": []
		}, {
			"id": 212,
			"name": "常熟",
			"upperid": 21,
			"path": [2, 21, 212],
			"children": []
		}]
	}, {
		"id": 22,
		"name": "无锡",
		"upperid": 2,
		"path": [2, 22],
		"children": []
	}]
}, {
	"id": 3,
	"name": "福建",
	"upperid": "",
	"path": [3],
	"children": [{
		"id": 31,
		"name": "福州",
		"upperid": 3,
		"path": [3, 31],
		"children": []
	}, {
		"id": 32,
		"name": "厦门",
		"upperid": 3,
		"path": [3, 32],
		"children": []
	}]
}]

获取选中节点树(包括父节点)

[{
	"id": 1,
	"name": "浙江",
	"upperid": "",
	"path": [1],
	"children": [{
		"id": 11,
		"name": "杭州",
		"upperid": 1,
		"path": [1, 11],
		"children": []
	}, {
		"id": 12,
		"name": "嘉兴",
		"upperid": 1,
		"path": [1, 12],
		"children": [{
			"id": 121,
			"name": "嘉善",
			"upperid": 12,
			"path": [1, 12, 121],
			"children": []
		}]
	}]
}, {
	"id": 2,
	"name": "江苏",
	"upperid": "",
	"path": [2],
	"children": [{
		"id": 21,
		"name": "苏州",
		"upperid": 2,
		"path": [2, 21],
		"children": [{
			"id": 211,
			"name": "吴江",
			"upperid": 21,
			"path": [2, 21, 211],
			"children": []
		}]
	}]
}]

<think>首先,用户的问题是关于Python递归的知识,包括概念、使用方法和示例。我需要根据系统指令来构建回答。 系统指令关键点: - 所有行内数学表达式用$...$格式。 - 独立公式用$$...$$格式并独立成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题,尽量保证回答真实可靠。 用户提供了几个引用: - 引用[1]:讨论递归的概念、注意事项、Python代码示例、使用场景。 - 引用[2]:Python递归函数的使用方法及实例。 - 引用[3]:Python递归及目录遍历,示例求和函数。 - 引用[4]和[5]:Python递归函数定义和注意事项,包括栈溢出风险。 用户说:“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。” 查看上下文,用户上一次的问题是“参考站内引用:引用[1]:...” 这似乎是用户提供的引用列表。用户当前查询是:“我想了解Python递归的相关知识,如概念、使用方法、示例等 请问Python递归的概念、用法及示例” 用户的上一次消息是系统指令的示例,然后用户发送了这个引用列表和当前查询。在我的响应中,我需要基于这些引用来回答,但要专注于用户的需求。 结构回答: 1. **概念介绍**:解释什么是递归。 2. **使用方法**:讨论如何在Python中实现递归。 3. **示例**:提供代码示例。 4. **注意事项**:包括栈溢出等问题。 5. **相关问题**:结尾生成相关问题。 回答需要用中文。 处理引用:我需要自然地添加引用标识。引用来自用户提供的[1]到[5],所以在回答中提到相关内容时,添加[^1], [^2]等。 例如: - 在解释递归概念时,引用[1]提到“递归是编程中的一种强大的技术,它允许函数调用自身”。 - 在示例部分,引用[3]提供了求和函数的例子:def sum2(n): ... - 在注意事项中,引用[5]提到栈溢出风险。 我的回答应该整合这些信息。 步骤: 1. **介绍递归概念**:解释递归是什么。 2. **使用方法**:如何在Python中定义递归函数。 3. **示例**:提供1-2个示例,比如递归求和(从引用[3])和另一个常见示例如阶乘或斐波那契数。 4. **注意事项**:讨论递归深度、栈溢出(引用[5])、尾递归优化等。 5. **生成相关问题**:结尾添加几个相关问题。 确保结构清晰:使用标题或分段。 数学表达式:如果有数学解释,比如递归关系,用$...$格式。例如,阶乘的递归定义:$n! = n \times (n-1)!$。 独立公式如果需要用$$...$$。 回答结构: - 开头:概述。 - 概念部分。 - 使用方法部分。 - 示例部分(代码)。 - 注意事项部分。 - 结尾:相关问题。 生成相关问题: - 类似示例中的“快速排序相关问题”。 - 例如: 1. 如何在Python中优化递归函数? 2. 递归和迭代的区别有哪些? 3. 递归在哪些实际场景中应用? 引用自然添加: - 例如,“递归允许函数调用自身来解决问题[^1]。” - 在代码示例后,添加引用如“[^3]”。 代码块:像示例一样展示代码。 </think>### Python递归概念、用法及示例 递归是编程中的一种核心技术,它允许一个函数内部调用自身来解决子问题,从而简化复杂任务的处理。在Python中,递归常用于处理具有自相似结构的问题,如树遍历、分治算法或数学序列计算。递归的核心在于定义**基准条件**(base case)和**递归步骤**(recursive step)。基准条件确保递归在满足特定条件时终止,防止无限循环;递归步骤则将问题分解为更小的实例。下面我将逐步解释概念、用法、示例和注意事项,确保回答真实可靠,基于用户提供的引用信息。 #### 1. 递归概念 递归基于数学归纳法原理:一个问题可以通过解决其较小版本来解决。例如,计算阶乘 $n!$ 可以用递归定义为: $$n! = n \times (n-1)! \quad \text{其中} \quad 0! = 1$$ 这在Python中体现为函数调用自身。递归的优势是代码简洁易懂,特别适合处理嵌套数据结构或算法(如二叉树搜索)。但需要谨慎设计,以避免常见陷阱如栈溢出[^1]。递归的本质是“分而治之”,将大问题分解为相似的小问题,直到达到基准条件[^5]。 #### 2. 使用方法 在Python中定义递归函数时,需遵循以下步骤: - **定义基准条件**:设置一个或多个条件来终止递归(例如,当输入达到最小规模时返回特定值)。 - **编写递归调用**:在函数体中调用自身,处理更小规模的输入。 - **确保收敛**:每次递归调用都应使问题规模减小,逐步逼近基准条件。 注意事项: - **栈溢出风险**:递归深度过大时,Python的调用栈可能溢出(默认深度约1000层)。可通过尾递归优化(tail recursion)或迭代代替来缓解[^5]。 - **效率考虑**:递归可能重复计算相同问题(如斐波那契数列),推荐使用缓存(如`functools.lru_cache`)优化。 - **适用场景**:递归适用于问题具有递归结构(如目录遍历、组合问题),但不适合实时性能敏感的场合[^2][^4]。 #### 3. 示例代码 以下是两个常见递归示例,展示概念和用法。第一个是求和函数(参考引用[3]),第二个是阶乘计算(展示递归定义)。 **示例1:递归求和函数** 此函数计算 $1 + 2 + \dots + n$ 的和,基准条件为 $n \leq 1$ 时直接返回 n。 ```python def sum_recursive(n): """递归计算1到n的和""" if n <= 1: # 基准条件 return n else: # 递归步骤 return n + sum_recursive(n - 1) # 测试运行 print(sum_recursive(100)) # 输出: 5050 ``` **运行结果**:输入100时输出5050,符合公式 $S_n = \frac{n(n+1)}{2}$[^3]。此代码适用于小规模计算,但n过大时可能栈溢出。 **示例2:递归阶乘函数** 阶乘 $n!$ 的递归定义为 $n! = n \times (n-1)!$,基准条件为 $n = 0$。 ```python def factorial(n): """递归计算n的阶乘""" if n == 0: # 基准条件 return 1 elif n < 0: # 处理无效输入 raise ValueError("n不能为负数") else: # 递归步骤 return n * factorial(n - 1) # 测试运行 print(factorial(5)) # 输出: 120 ``` **运行结果**:输入5时输出120,验证公式 $5! = 5 \times 4 \times 3 \times 2 \times 1 = 120$。此示例在n较大时也会面临栈溢出风险,建议对n > 1000使用迭代方法[^5]。 #### 4. 注意事项总结 - **栈溢出**:递归深度受Python栈大小限制,可通过`sys.setrecursionlimit()`调整,但不推荐;改用迭代更安全[^5]。 - **性能优化**:避免重复计算(如斐波那契数列),可使用动态规划或缓存装饰器。 - **调试技巧**:添加打印语句跟踪递归调用,确保基准条件正确设置。 - **适用性**:递归在文件系统遍历、算法设计(如快速排序)中高效,但日常编程中优先考虑可读性和效率[^1][^4]。递归深度大时,Python可能抛出`RecursionError`。 通过上述概念、用法和示例,您能掌握Python递归的基础。如需深入优化或特定场景应用,可参考Python官方文档或算法书籍。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值