我有一段代码,我怀疑它是通过其定义实现的递归。我的理解是代码必须调用自身,完全相同的功能。我还质疑是否以这种方式编写代码会增加额外的开销,这可以通过使用递归来看到。你有什么想法?
class dhObject
{
public:
dhObject** children;
int numChildren;
GLdouble linkLength; //ai
GLdouble theta; //angle of rot about the z axis
GLdouble twist; //about the x axis
GLdouble displacement; // displacement from the end point of prev along z
GLdouble thetaMax;
GLdouble thetaMin;
GLdouble thetaInc;
GLdouble direction;
dhObject(ifstream &fin)
{
fin >> numChildren >> linkLength >> theta >> twist >> displacement >> thetaMax >> thetaMin;
//std::cout << numChildren << std::endl;
direction = 1;
thetaInc = 1.0;
if (numChildren > 0)
{
children = new dhObject*[numChildren];
for(int i = 0; i < numChildren; ++i)
{
children[i] = new dhObject(fin);
}
}
}
void traverse(void)
{
glPushMatrix();
//draw move initial and draw
transform();
draw();
//draw children
for(int i = 0; i < numChildren; ++i)
{
children[i]->traverse();
}
glPopMatrix();
}
void update(void)
{
//Update the animation, if it has finished all animation go backwards
if (theta <= thetaMin)
{
thetaInc = 1.0;
} else if (theta >= thetaMax)
{
thetaInc = -1.0;
}
theta += thetaInc;
//std::cout << thetaMin << " " << theta << " " << thetaMax << std::endl;
for(int i = 0; i < numChildren; ++i)
{
children[i]->update();
}
}
void draw(void)
{
glPushMatrix();
glColor3f (0.0f,0.0f,1.0f);
glutSolidCube(0.1);
glPopMatrix();
}
void transform(void)
{
//Move in the correct way, R, T, T, R
glRotatef(theta, 0, 0, 1.0);
glTranslatef(0,0,displacement);
glTranslatef(linkLength, 0,0);
glRotatef(twist, 1.0,0.0,0.0);
}
};
答案 0 :(得分:6)
这是定义/挑剔的问题。在这个C函数中:
void traverse( tree * t ) {
if ( t != 0 ) {
traverse( t->right );
traverse( t->left );
}
}
函数是递归的吗?我会说是的,即使它是在不同的对象上调用的。所以我会说你的代码也是递归的。举一个更极端的例子:
unsigned int f( unsigned int n ) {
if ( n = 0 ) {
return 0;
}
else {
return f( n - 1 ); // XXX
}
}
在XXX上调用函数的事情显然与最初调用的函数不同。但我认为每个人都会同意这是一个递归函数。
答案 1 :(得分:5)
是的,因为你有自己的某些功能。根据定义,它是直接递归。如果你有函数A()
调用函数B()
,函数B()
依次(直接或间接)调用函数A()
,你也可以有间接递归试。
答案 2 :(得分:1)
看起来像traverse()和update()方法中的递归,深度由对象集合的物理几何控制。
如果这是你的实际课程,我会推荐一些东西:
在使用之前检查numChildren的上限,以免有人错误地传入一个非常大的数字。
如果这将在线程环境中使用,您可能希望同步对子对象的访问。
考虑使用容器而不是分配数组。我没有看到析构函数,所以如果这个对象被删除,你就会泄漏数组存储和子节点的内存。
答案 3 :(得分:1)
如果您担心的是递归的开销,那么重要的是测量堆栈的深度。如果您的堆栈是100个深度调用,那么无论您是否以递归方式工作都无关紧要。
答案 4 :(得分:0)
调用这些方法之一(遍历或更新)将具有为每个孩子调用相同方法的效果。所以,这些方法不是递归的。相反,它是一种递归算法:它以递归方式应用于对象的逻辑树上。
调用堆栈的深度直接由算法运行的数据结构决定。
真正发生的是这个(伪代码):
Function Traverse(object o)
{
[do something with o]
Foreach(object child in o.Children)
Traverse(child);
[do something with o]
}