子集树
Posted ExitQuit
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了子集树相关的知识,希望对你有一定的参考价值。
最近上班上到脑袋都晕,,,突然想到要复习一下。就搞了个子集树的代码。。
其实子集树有点像暴力破解,大名鼎鼎的0-1规划中的背包问题一样。假设有N个背包,对应N个元素。
那么有:
背包 | 1 | 2 | 3 | ... | n |
要/不要 | 要/不要 | 要/不要 | 要/不要 | 要/不要 | 要/不要 |
然后要、不要分别对两种情况,好比二叉树的左子树和右子树一样。
子集树写法也参考了背包问题,遍历N个背包,分别决定要不要该背包,然后遍历整棵树。
当发现遍历层数满了以后,就打印路径即可~
if num == len(arr):
outputList.append([arr[index] for index in range(0, num) if cur_arr[index] ])
return
当层数未满,那么继续尝试
1、要该背包
2、不要该背包
对应代码:
# 选第num个元素 cur_arr[num] = 1 subSetTree(arr, cur_arr, num + 1, outputList) # 不选第num 个元素 cur_arr[num] = 0 subSetTree(arr, cur_arr, num + 1, outputList)
那么问题来了,如果将该元素append进一个数组中,然后执行完了再弹出可以吗?
【不可以】原理很简单,这个子集树肯定遍历该树的所有路径,如果往里面append元素,那么必然会涉及到重复添加元素。。。必然涉及到处理以后情况
1、某一路径到头了,可能回头走若干步,然后再继续往下走。。。这时候涉及的问题就巨复杂了。。。
2、由于递归之后,数组中的元素大小已经发生了变化,这时候如果使用
cur_arr[num] = cur_arr[:-1]
会导致修改错数据。。。。
3、反正这种处理是巨恶心的。。。
def subSetTree(arr, cur_arr, num, outputList): if num == len(arr): outputList.append([arr[index] for index in range(0, num) if cur_arr[index] ]) return # 选第num个元素 cur_arr[num] = 1 subSetTree(arr, cur_arr, num + 1, outputList) # 不选第num 个元素 cur_arr[num] = 0 subSetTree(arr, cur_arr, num + 1, outputList) def subSetTree(arr, cur_arr, num, outputList): if len(arr) == num : outputList.append([val for val in cur_arr if val != None]) return # 选第num个元素 cur_arr[num] = arr[num] subSetTree(arr, cur_arr, num + 1, outputList) # 不选第num 个元素,删除第num个元素 cur_arr[num] = None subSetTree(arr, cur_arr, num + 1, outputList) arr = [1, 2, 3] cur_arr = range(0,3) outputList = [] num = 0 subSetTree(arr, cur_arr, num, outputList) for arr in outputList: print arr
以上是关于子集树的主要内容,如果未能解决你的问题,请参考以下文章