二叉树遍历导致堆栈溢出

时间:2015-05-13 17:43:41

标签: c recursion tree stack-overflow traversal

所以我正在通过数组实现二进制搜索树(如果父级索引是i,那么左子索引是(i * 2 + 1),右子索引是(i * 2 + 2)。

每当我试图遍历树(预先排序)时,我在第3个预订函数调用期间遇到堆栈溢出。

这是我的预订功能代码:

void traversePreOrder(Tree tree, int index)
{
    printf("%d\n", index); //debug
    if (tree.data[index].accNumber != 0) //all .accNumber values are initialized as 0
                                   // at the start of the program to mark empty nodes.
    {
        printf("printing: %d\n", index); //debug
        printNode(tree.data[index]);

        if (tree.data[index * 2 + 1].accNumber != 0)
        {
            printf("will print: %d\n", index * 2 + 1); //debug
            traversePreOrder(tree, index * 2 + 1);
        }

        if (tree.data[index * 2 + 2].accNumber != 0)
        {
            printf("will print: %d\n", index * 2 + 2); //debug
            traversePreOrder(tree, index * 2 + 2);
        }
    }
    else
        return;
}

以下是预订遍历的输出:

0
printing: 0
User: Dumbledore
Account number: 53167
Account type: public
Account balance: 4597.54
Is account in debt? Yes

will print: 1
1
printing: 1
User: Stark
Account number: 13497
Account type: private
Account balance: 1549.50
Is account in debt? No

will print: 3

Process returned  255 (0xFF)   execution time : 5.856 s
Press any key to continue.

树应该看起来像:

(only accNumber values)
                    53167
                  /       \
              13457      74310
                 \       /   \
               43158  71401  79473
                /      /       \
             14741   69690    99751

感谢您的帮助。

更新

将最大树容量从1000更改为50以某种方式解决了这个问题。如果有人可以解释原因,那就太好了。

1 个答案:

答案 0 :(得分:1)

你声明:

  

所有.accNumber值在程序开始时初始化为0   标记空节点。

这不是一个足够强大的递归停止标准。

如果你想要明确,你应该在索引的上限,并确保你不超过它。例如:如果tree.size iz是树中节点的数量,那么在递归的每个步骤之前也应该进行查询,如下所示:

    int left_child_idx = index * 2 + 1;
    if (tree.data[left_child_idx].accNumber != 0 && left_child_idx < tree.size)
    {
        printf("will print: %d\n", index * 2 + 1); //debug
        traversePreOrder(tree, index * 2 + 1);
    }

或者,如果你不想这样做,你应该确保有两个终止叶子,0 accNumber 所有你的最后一个节点。

在这个数据结构中,实际上意味着data数组的后半部分应该只包含这样的终止叶子。

看起来很难看,但我希望你能看到它:

                      53167
                  /           \
              13457             74310
             /   \            /       \
            0      43158     71401     79473
          /  \     /   \     /    \      /  \
         0    0   14741  0  69690  0    0   99751
        /\    /\   /\    /\   /\   /\   /\   /\
       0  0  0  0 0  0  0  0 0  0 0  0 0  0 0  0    

作为一个阵列:

[53167, 13457, 74310, 0, 43158, 71401, 79473, 0, 0, 14741, 0, 69690, 0, 0, 99751,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 

有31个元素,99751是第15个元素。下半场的任何一个都不会为零,你会得到溢出。