2012-04-23 61 views
1

我有父节点和子节点,像这样由树形数据结构:如何访问调用堆栈?

<Node1> 
    <Node2/> 

    <Node3> 
    <Node4/> 
    </Node3> 
</Node1> 

并解析结构我使用的是μ-递归函数:

void RecursiveFunction(NodeT node) 
{ 
    if(node.has_child()) 
     RecursiveFunction(node.child()); 
} 

当我打电话RecursiveFunction作为参数传递,例如Node2,我希望有权访问父节点(Node1)的数据,而不使用额外的数据结构存储这些数据,因为在进行递归调用之前,第一个节点的数据已存储在调用堆栈中。所以我需要访问调用堆栈来读取Node1的数据,而我正在解析Node2无法直接访问父节点,等等。

例如,如果我解析节点4:

void RecursiveFunction(NodeT node) 
{ 
    /* Access to Node3 and Node1 data... 

    if(Node4.has_child()) 
     RecursiveFunction(Node4.child()); */ 
} 

这可能吗?以什么方式?

谢谢。

+3

这是一个非常糟糕的主意。如果你想这样做,在'NodeT'中包含一个父指针。试图弄乱堆栈中的地址将会是a)混乱,b)极不可移植,c)可能不可靠。 – delicateLatticeworkFever 2012-04-23 11:44:44

+1

为什么不把这个状态存储在Node中,然后执行'node.parent()'? – RedX 2012-04-23 11:45:19

+0

你让我看着'μ递归'。 – 2012-04-23 11:48:50

回答

1

这是可能的,但这样做会非常危险。这主要是因为你想混淆进程堆栈。我也不认为有任何库函数可以这么做,据说你必须做一些指针算术来实现这一点。

1

即使你会找到一种方法来访问调用函数中的数据,对于其他程序员来说,理解你所做的事情并不容易。

我会建议通过迭代替换递归,这应该允许你清楚地表达你想要做什么。有关更多信息,请参阅Way to go from recursion to iteration

1

访问调用堆栈对我而言有点过度工程。将函数从递归转换为迭代并使用您自己的堆栈。堆栈应包含一个NodeT实例和一个通知该函数的整数值,该节点的子节点已经处理了多少个。如果此值低于节点的子节点数,则循环将递增此值并将下一个子节点添加到堆栈中。否则,它将处理该节点,然后从堆栈中弹出它。

另一个优点是,您不再受程序堆栈大小的限制,并且如果存在这样的需求,您可以处理更多嵌套结构的方式。否则,你会冒险,好吧,我们不要害怕,堆栈溢出。

0

如果您希望或必须(例如,家庭作业要求?)坚持递归,请将父节点作为第二个参数添加到您的函数中,该函数默认为NULL,表示当前节点是根节点。即:

void RecursiveFunction(NodeT const& node, NodeT const* parentPtr=NULL) 
{ 
    if(node.has_child()) 
     RecursiveFunction(node.child(), &node); 
} 

请注意,我修改你的函数接受引用常量的第一个参数,否则你创建你的树副本的很多

+0

没有作业,没有参考,仅仅是因为这是一个示例。无论如何,我如何访问parentPtr的父项? – gliderkite 2012-04-23 12:01:40

+0

如果你需要,你需要在'NodeT'类型中包含这些信息。 – 2012-04-23 12:03:49

+0

正如我写的,我无法直接访问父亲与我的数据结构。 – gliderkite 2012-04-23 12:04:53

0

调用栈用于功能参数,以及*,所以用它来建立链:

struct chain { 
    NodeT* node; 
    chain const* parent; 
} 
void RecursiveFunction(chain const& c) 
{ 
    if(c.node->has_child()) { 
     chain child = { c.node->child(), &c }; 
     RecursiveFunction(child); 
    } 
} 

[*]至少在概念上;实际实施可能会有所不同在任何情况下,这个C++代码都是可移植的,不像低级别的黑客。