在递归函数中返回和使用多个树结构

时间:2009-12-27 00:57:46

标签: c recursion tree traversal

我有一个函数get_trees(),它在一个复杂的树结构T上运行,并返回两个组件树结构A和B.我能够让它工作的唯一方法是创建一个带有指针的新结构C. A和B,然后作为参数传递给函数,也是一个返回值:

typedef struct Composite {
itree *A;
itree *B; 
} composite;

composite *get_trees(complextree *T, itree *A, itree *B, composite *C);

树木的根节点A& B在另一个函数中初始化:

itree *A = new_itree(0);
itree *B = new_itree(0);
A->n     = T->a;
B->n     = T->b;
composite *C;
C = get_trees(T, A, B, C);

get_trees()遍历complextree T的分支,分配并填充A和B的节点,并在子节点上递归调用自身。简化代码:

//code for allocating subnodes of A and B     
if (T->nodes != NULL){
    for (i=0; i< T->nn; i++){
    //code for computing p & q
    C = get_trees(T->nodes[i], A->nodes[p], B->nodes[q]);
    }
}

代码工作正常。但是看起来很难看。

(1)C没有内在含义,即用于允许返回多个值。有替代方案吗?以下内容:

(2)是否可以使用以下签名编写递归函数:

void get_trees(T, A, B);

如果我通过A&amp;的根节点,似乎B作为参数和子节点在递归函数中分配,然后有一个连续的命令链可以说,并且在递归调用完成时整个树应该可用。它对我不起作用,所以绝不允许这样做。如果有人可以解释为什么会这样,或者如果可以提供更优雅的解决方案,我将不胜感激?

谢谢,节日快乐。 〜RT

3 个答案:

答案 0 :(得分:1)

您所做的是将多个指针值作为函数的返回值返回的唯一方法。但它不被认为是好的形式。

良好的形式是声明你的函数有参数和参数,并使用返回值来表示成功或失败。像这样

bool get_trees(complextree *T, itree *A, itree *B, composite *C, itree ** AOut, itree** BOut); 

答案 1 :(得分:0)

是的,传递一个指向调用者复合的指针会让函数使用它来存储结果。当然,首先在堆栈或堆上创建复合对象至关重要......

   composite c;
   get_trees(&c);

   composite *c = malloc...
   get_trees(c)

当然该函数实际上可以返回一个将被复制到调用者的结构,但我只会在有限的情况下使用该样式...

答案 2 :(得分:0)

这是一个更简单的问题版本。假设我们有一个节点:

typedef struct Node {
    int n; // number of sub-nodes
    int i; // data
    node  **nodes;//subnodes
} node;

现在,下面的代码克隆了树结构,数据值加倍(没有任何错误检查)。

node *double_tree( node *A, node *B ) {
  if ( B == NULL ) {
    B = (node*) calloc( 1, sizeof (node ) );
  }
  B->i = 2 * A->i;
  B->n = A->n;
  if ( A->nodes != NULL ) {
    B->nodes = (node **) calloc( 1, A->n * sizeof (node* ) );
    int ii;
    for ( ii = 0; ii < A->n; ii++ ) {
        B->nodes[ii] = double_tree( A->nodes[ii], B->nodes[ii] );
    }
  }
  return B;
}

我原来的问题涉及两个变种:

(a)有多个返回树(比如double_tree,square_tree)。

(b)返回树的结构与输入树不同。

似乎核心问题是“在函数内部分配的结构必须作为函数输出'返回'作为指针”,只是将指针作为参数传递不起作用。我希望我错了,并且有更好的方法来做到这一点。

再次感谢你的帮助,Russ