使用链表结构遍历树

时间:2015-09-21 09:40:50

标签: c algorithm

我有一个包含next和child的struct节点。

struct Node{
Node *parent;
Node *next;
Node *child;
}

下图显示了树的结构。

我如何编写遍历该树的函数?没有递归? enter image description here

我脑子里有一个伪代码,但不确定它是否正确,因为每个节点都有一个孩子,我也需要使用那个孩子进行搜索

while ( root !=NULL)
{

root = root->next;
}

我想访问所有节点。

3 个答案:

答案 0 :(得分:2)

我猜你的树看起来像这样:

-> grandma
    -> dad
        -> me
        -> sister
            -> niece
        -> brother
    -> uncle
        -> cousin

其中缩进意味着一定程度的祖先。递归函数很简单:

void traverse_rec(const Node *node)
{
    if (node) {
        process(node);
        traverse_rec(node->child);
        traverse_rec(node->next);
    }
}

这可以重写为循环。如果当前节点有子节点,那就是下一个要访问的节点。否则,你想访问它的兄弟姐妹。但该节点实际上可能没有兄弟姐妹。因为您有到父节点的链接(并且根节点的父节点应该是'NULL),所以您可以回溯树,直到找到要跟随的兄弟节点或节点为NULL

void traverse2(const Node *node)
{
    while (node) {
        puts(node->name);

        if (node->child) {
            node = node->child;
        } else {
            while (node && node->next == NULL) {
                node = node->parent;
            }

            if (node) node = node->next;
        }
    }
}

这比递归函数更复杂,但它可以转换为类似迭代器的代码,在那里得到下一个节点:

const Node *next(const Node *node)
{
    if (node == NULL) return NULL;
    if (node->child) return node->child;

    while (node && node->next == NULL) {
        node = node->parent;
    }

    if (node) return node->next;
    return NULL;
}

使用这个“迭代器”,您可以编写如下代码:

for (const Node *p = root; p; p = next(p)) {
    puts(p->name);
}

答案 1 :(得分:1)

树按队列转换为班轮列表。并处理班轮列表的每个节点。

伪代码(未经测试):

enqueue(q, root);//queue *q;
while(NULL!=(current_node = dequeue(q))){
    //do stuff current_node

    if(has_child(current_node)){//unnecessary, include for-loop
        for(node = current_node->child; node != NULL; node = node->next){
            enqueue(q, node);
        }
    }
}

答案 2 :(得分:1)

深度优先遍历可以通过以下方式完成,无需父指针:

  std::stack<Node*> Q; Q.push(root);
  while(!Q.empty())
  {  Node* node = Q.top(); Q.pop();
     // visit the node, do stuff
     if(node->next) Q.push(node->next);
     if(node->child) Q.push(node->child);
  }

注意它是深度优先的,因为在相同级别的节点之前将访问子节点(如果有的话),这些节点通过 next 指针链接。