如何在C中打印级别订单树(非二进制)?

时间:2012-08-19 15:28:39

标签: c data-structures tree

我正在查看此处提出的问题,但只找到了有关二叉树的答案。 我想按等级打印一个有0到n个孩子的树。 我知道孩子的数量,但我的代码不起作用

我认为的算法是:

  • print root
  • 打印所有儿童数据
  • 为每个孩子
    • 打印数据

但问题是我不知道在哪里停止,当我递归尝试时,我失败了。

这是我写的功能:

void printBFS(myStruct s)
   {
      int i = 0;
      printAllChildrenData(s);
      for (i = 0; i < s->number_of_children; i++)
        {
            myStruct childCurr = getChildAtIndex(s, i);
            printBFS(chilCurr);
        }
   }

我在弄乱这里的东西。 我希望功能清楚: printAllChildrenData打印S的所有子项的所有数据;它遍历子列表并打印出来。

编辑 如果我有这样的树例如:

           1
     2        7        8
  3    6            9     12
 4 5              10 11

它应该打印:

1 2 7 8 3 6 4 5 9 12 10 11

而不是:

1 2 7 8 3 6 9 12 4 5 10 11

3 个答案:

答案 0 :(得分:1)

你可以使用像printElementsAtLevelN(int n)这样的函数来遍历树,跟踪它的深度,并且只打印正确级别的元素。如果你有它返回打印的元素数量,你可以有一个类似于:

的循环
while (printElementsAtLevelN( n ))
{
    n++;
}

这样做的缺点是你遍历树的一部分很多次,但如果树不大,那可能不是问题。

答案 1 :(得分:1)

此代码紧密基于您的代码(但扩展为SSCCE),会产生输出:

 1 2 7 8 3 6 4 5 9 12 10 11

代码使用C99的指定初始化程序功能(C99,IMNSHO最有用的补充之一)。我选择使用比myStruct更好的名称来表示结构;它代表一棵树,所以它就是它所谓的。我也没有将指针隐藏在typedef中,并使打印代码保持正确(打印代码通常不应修改它正在操作的数据结构)。它还使用C99选项在for循环的第一个子句中声明变量。我引入了一个额外的函数printTree(),它打印来自根节点的数据,调用你的printBFS()来打印树的主体,并打印一个换行符来标记输出的结尾;调用printTree()函数来打印树。请注意系统使用printData()打印节点的数据。如果数据比单个整数更复杂,则允许您编写一次打印代码。

仔细研究代码会显示下面的printBFS()与您展示的内容同构,这反过来表明您的问题不在您展示的代码中。这意味着它可能在您用于构建树的代码中,而不是在用于打印它的代码中。由于您没有向我们展示树木构建代码,因此我们很难预测问题所在。

#include <stdio.h>
#include <assert.h>

enum { MAX_CHILDREN = 3 };
typedef struct Tree Tree;

struct Tree
{
    int data;
    int number_of_children;
    Tree *children[MAX_CHILDREN];
};

static void printData(const Tree *s)
{
    printf(" %d", s->data);
}

static void printAllChildrenData(const Tree *s)
{
    for (int i = 0; i < s->number_of_children; i++)
        printData(s->children[i]);
}

static const Tree *getChildAtIndex(const Tree *s, int i)
{
    assert(s != 0 && i >= 0 && i < s->number_of_children);
    return(s->children[i]);
}

static void printBFS(const Tree *s)
{
    printAllChildrenData(s);
    for (int i = 0; i < s->number_of_children; i++)
    {
        const Tree *childCurr = getChildAtIndex(s, i);
        printBFS(childCurr);
    }
}

static void printTree(const Tree *s)
{
    printData(s);
    printBFS(s);
    putchar('\n');
}

/*
**             1
**       2        7        8
**    3    6            9     12
**   4 5              10 11
*/

static Tree nodes[] =
{
    [ 1] = {  1, 3, { &nodes[ 2], &nodes[ 7], &nodes[ 8] } },
    [ 2] = {  2, 2, { &nodes[ 3], &nodes[ 6], 0          } },
    [ 3] = {  3, 2, { &nodes[ 4], &nodes[ 5], 0          } },
    [ 4] = {  4, 0, { 0,          0,          0          } },
    [ 5] = {  5, 0, { 0,          0,          0          } },
    [ 6] = {  6, 0, { 0,          0,          0          } },
    [ 7] = {  7, 0, { 0,          0,          0          } },
    [ 8] = {  8, 2, { &nodes[ 9], &nodes[12], 0          } },
    [ 9] = {  9, 2, { &nodes[10], &nodes[11], 0          } },
    [10] = { 10, 0, { 0,          0,          0          } },
    [11] = { 11, 0, { 0,          0,          0          } },
    [12] = { 12, 0, { 0,          0,          0          } },
};

int main(void)
{
    printTree(&nodes[1]);
    return(0);
}

您可以轻松修改测试以依次打印每个节点:

enum { NUM_NODES = sizeof(nodes) / sizeof(nodes[0]) } ;

int main(void)
{
    for (int i = 1; i < NUM_NODES; i++)
        printTree(&nodes[i]);
    return(0);
}

答案 2 :(得分:0)

您需要一个列表结构(或其他一些容器)。伪代码将遵循:

ListOfNodes list
ListOfNodes children
add_node(list, root)
repeat {
    while (list not empty) {
        print top_node(list)
        add_children(children, top_node)
        pop_top(list)
    }
    list = children
    clear_all(children)
} until (list is empty)