我是编码的新手,我正在尝试回溯一个示例问题来打印给定数字集合中的所有子集,其中成员总数等于给定值。
我面临一个非常奇怪的问题,下面的代码恰好运行良好,并在ideone.com等在线编译器上提供所需的输出,但在我的系统上输出错误。我能否解释为什么会发生这种情况以及可能的原因?
//works well on online compilers
#include<stdio.h>
#include<stdlib.h>
void printArray(int *a, int n)
{
int i;
for(i=0;i<n;i++)
printf("%d ",a[i]);
printf("\n");
return;
}
void subsetSum(int *set, int *tuple, int setSize, int tupleSize, int current, int sum, int const target)
{
if(sum==target)
{
printArray(tuple,tupleSize);
subsetSum(set,tuple,setSize,tupleSize-1,current+1,sum-set[current],target);//call further for items excluding this one
}
else
{
int i;
for(i=current;i<setSize;i++)
{
tuple[tupleSize]=set[i]; //add the ith node to tuple and move down for backtracking
subsetSum(set,tuple,setSize,tupleSize+1,i+1,sum+set[i],target); ///after this backtrack to other possible nodes
}
}
return;
}
void getSubsets(int *set, int size, int const target)
{
int *tuple=(int*)malloc(size*sizeof(int));
subsetSum(set,tuple,size,0,0,0,target);
free(tuple);
return;
}
int main(void)
{
int weights[] = {10, 7, 5, 18, 12, 20, 15};
int size = 7;
getSubsets(weights, size, 32);
return 0;
}
预期输出(与ideone一样)
10 7 15
7 5 20
5 12 15
12 20
pc上的错误输出
10 7 15
10 7
10
7 5 20
5 12 15
5 12
5
12 20
答案 0 :(得分:2)
我相信您正在读取set[]
数组的末尾(分配为tuple[]
),这会导致未定义的行为(UB)。
i=6
(setsize-1
)。然后致电:
subsetSum(set,tuple,setSize,tupleSize+1, (setsize-1)+1, sum+set[i],target);
这意味着在subsetSum()
的函数调用current == setsize
。
假设您sum==target
打印数组(很好)但是你做了:
subsetSum(set,tuple,setSize,tupleSize-1, setsize+1, sum-set[setsize],target);
在set[setsize]
电话中溢出。
在printArray()
删除缓冲区溢出后删除递归函数调用,因此UB和工作正常。它最初在一个编译器/环境中“工作”的原因仅仅是由于UB的性质......有时它似乎正常工作。
答案 1 :(得分:0)
不确定为什么ideone版本似乎有用,但无论如何,我认为你不需要在第一个if块中使用这一行:
subsetSum(set,tuple,setSize,tupleSize-1,current+1,sum-set[current],target);//call further for items excluding this one
&#34;回溯&#34;每个堆栈层返回时都会发生。