【问题标题】:Optimizing binary tree gives weird duplication errors优化二叉树会产生奇怪的重复错误
【发布时间】:2013-09-10 14:45:26
【问题描述】:

我正在尝试实现一个 optimize 方法,该方法应该使二叉树完整。我的方法是通过将树排序为int*,然后将数组的中点添加到一个新数组并在每一半递归。

但是,代码实际输出的是在沿左侧树下降到最大深度后生成重复项:

16 8 4 2 1 0 0 3 3 6 5 5 7 7 12 10 9 9 11 11 14 13 13 15 15 24 20 18 17 17 19 19

我一生都无法弄清楚为什么会发生这种情况。

我的代码:

// bth is "binary tree helper [method]"
void bth_optimizearray(int* in, int* out, int min, int max, int* i) {
    // `in' is sorted, `out' should be optimized
    // `i' is the current index in `out'

    int len /* of subarray */ = max - min;
    if (len < 1) {
        // empty subarray
        return;
    }
    if (len == 1) {
        // just add it
        out[(*i)++] = in[min];
    } // else

    // Add the midpoint
    int midpos = min + ((max - min) >> 1);
    out[(*i)++] = in[midpos];
    bth_optimizearray(in, out, min, midpos, i);
    bth_optimizearray(in, out, midpos + 1, max, i);
}

void bt_optimize(bintree *tree) {
    int treesize = bt_size(tree);

    int *ordered = malloc(treesize * sizeof(int));
    {
        int i = 0;
        void visit(node *n) {
            ordered[i++] = n -> key;
        }
        bt_traverse(tree, INORDER, visit);
    }


    int *optimized = malloc(treesize * sizeof(int));
    {
        int *i = malloc(sizeof(int));
        (*i) = 0;
        bth_optimizearray(ordered, optimized, 0, treesize, i);
    }

    // Free all nodes (but don't call freetree; that would free the tree too)
    void freenode(node *n) {
        free(n);
    }
    bt_traverse(tree, INORDER, freenode);
    tree -> root = NULL;

    {
        int i;
        for (i = 0; i < treesize; i++) {
            printf("%d ", optimized[i]);
            bt_add(tree, optimized[i]);
        }
    }
}

在此代码中,bintree 是 struct { node *root; int size; },所有其他方法都可以正常工作。

完整代码也是on GitHub,但是这个bt_optimize方法只在optimize分支中。

这是 C,而不是 C++。

有什么建议吗?

【问题讨论】:

    标签: c pointers binary-tree


    【解决方案1】:

    好像min = max - 1时,"out[(*i)++]语句运行了两次。

    if (len == 1) {
        // just add it
        out[(*i)++] = in[min];
        // -- Should place a "return;" here?
    } // else
    
    // Add the midpoint
    int midpos = min + ((max - min) >> 1);
    out[(*i)++] = in[midpos];
    

    【讨论】:

    • 不错的收获!这是未能完全修改一些早期代码的结果。谢谢。
    【解决方案2】:

    我觉得这段代码很可疑:

    out[(*i)++]
    

    原因是这样它将“i”的值作为索引,然后它会增加值。

    为了证明这一点,我进行了测试。示例:

    int index,value;
    index = 10;
    
    value = index++;//this way value will become 10 and index 11
    
    index = 10;
    
    value = ++index;//this way both become 11
    

    【讨论】:

    • 这是应该做的。
    • 那部分 "if(len==1){ //code stuff}//else" 为什么 else 只有一个注释?无论哪种方式,您有时都会添加两次并增加索引两次(这会导致堆栈溢出)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-15
    • 1970-01-01
    相关资源
    最近更新 更多