我有一个递归函数,它从一组n中产生长度为k的所有组合。通常称为“nCk”(“n选择k”)。我希望用相当大的值(56C22)来放松它,这将产生2,142,582,442,263,900个结果。由于实施限制(我必须使用VBScript,并且不能保持登录计算机的时间比我工作的时间长),我将无法让它一次性完成运行。因此,我想定期保存函数的当前状态并在以后恢复...但我似乎无法弄清楚如何这样做。递归正在弄乱我通过逻辑思考这个问题的能力。
我已经在SO上仔细阅读了建议的解决方案,否则搜索“恢复递归函数”等等,但无济于事。我会很感激一些指针(不是编程语言双关语)让我走上正轨。
实际算法(伪代码很好)优于不包含实际代码的冗长解释。如果你想实际编写代码,我最熟悉的是C,C ++,Pascal,VB,JavaScript和VBScript(如上所述,目前正在使用VBScript)。
这是我的递归函数:
function nCk(aSet, iSetIndex, aSubset, iSubsetIndex)
'Found result
if (iSubsetIndex > ubound(aSubset)) then
log "output.txt", join(aSubset), 1, false
exit function
end if
'No more characters available
if (iSetIndex >= ubound(aSet) + 1) then
exit function
end if
'With aSet[iSetIndex]
aSubset(iSubsetIndex) = aSet(iSetIndex)
nCk aSet, iSetIndex + 1, aSubset, iSubsetIndex + 1
'Without
nCk aSet, iSetIndex + 1, aSubset, iSubsetIndex
end function 'nCk
仅供参考:我今年50岁;这不是作业。
答案 0 :(得分:0)
我不确定您的特定语言实现,但我相信在某些情况下将递归转换为迭代是有用的。当你有一个明确的堆栈时,将它写入光盘并从你离开的地方拿起来应该不会太复杂。
一般例子:
stack = [[argument1,argument2,argument3,...etc.]]
while stack is not empty
current_parameters = stack.pop
aSet = current_parameters[0]
iSetIndex = current_parameters[1]
...etc.
if ...
else ...
// push to stack instead of calling nCk
stack.push([aSet, iSetIndex + 1, aSubset, iSubsetIndex + 1])
if it's time to go home
write stack to disc
break
答案 1 :(得分:0)
存储递归并不容易,因为要恢复操作,您需要恢复堆栈,这不是一项简单的任务。我会使用迭代算法,这不像递归那样优雅。但如果需要中断/恢复计算,它会得到回报。
一个想法可能是:
作为算法(首先,迭代所有子集):
def calc_subsets(state, N):#N - number of elements in the original set
while True: #just iterate
if storeFlag:#you need to set this flag to store and interrupt
store(state)
return
if len(state)==N and state[-1]!=-1: #a full subset is reached
evaluate(state)
state.append(-1)#mark for unwind
if state[-1]==-1:#means unwind state
state.pop()
if not state: #state is empty
return #unwinded last element, we are done
if state[-1]==1:#there is noting more to be explored
state[-1]=-1#mark for unwind in the next iteration
else:# = 0 is explored, so 1 is the next to explore
state[-1]=1
else: #means explore
state.append(0) # 0 is the first to explore
evaluate
取决于你,我只打印出矢量:
def evaluate(state):
print state
要打印3个元素的所有子集,应该调用:
calc_subsets([0], 3)
>>>
[0, 0, 0]
[0, 0, 1]
[0, 1, 0]
[0, 1, 1]
[1, 0, 0]
[1, 0, 1]
[1, 1, 0]
[1, 1, 1]
并仅打印第二部分:
calc_subsets([0,1,1,-1], 3)
>>>
[1, 0, 0]
[1, 0, 1]
[1, 1, 0]
[1, 1, 1]
现在,该算法可以适用于仅通过给定基数的所有子集进行迭代。为此,必须跟踪当前子集中的元素数量并触发展开(通过将-1推入状态向量),如果实现了所请求的子集大小。