使用inorder遍历删除二叉树

时间:2015-10-28 09:47:45

标签: c data-structures tree binary-tree

我正在学习如何使用Postorder遍历删除二叉树。我知道要删除节点,首先我们需要删除它的子节点,然后删除节点本身,因此Postorder遍历最适合删除二叉树。我想使用Inorder遍历做同样的事情,一切正常,但我不明白下面的代码是如何工作的?

#include<stdio.h>
#include<malloc.h>

struct b_tree{
    int data;
    struct b_tree *left,*right;
};

typedef struct b_tree tree;

tree* create_node(int data)
{
    struct b_tree* new_node=(tree*)malloc(sizeof(tree));
    new_node->data=data;
    new_node->left=NULL;
    new_node->right=NULL;
    return new_node;
}

void delete_tree(tree *root)
{
    if(root==NULL)
        return;
    delete_tree(root->left);
    printf("Deleting %d node.\n",root->data);
    free(root);
    delete_tree(root->right);
}

int main()
{
    tree *root=NULL;
    root=create_node(1);
    root->left=create_node(2);
    root->right=create_node(3);
    root->left->left=create_node(4);
    root->left->right=create_node(5);
    root->left->right->left=create_node(6);
    root->left->right->right=create_node(7);
    root->right->right=create_node(8);
    root->right->right->left=create_node(9);
    delete_tree(root);
    root=NULL;
    return 0;
}

Tree
根据Inorder遍历要删除的第一个节点是4,然后是2,但是一旦我们释放2它应该丢失所有数据,意味着它不应该保留指针对于正确的节点5,但即使在2被释放后,其左子5仍然被遍历,但不应该因为节点2已被释放而发生。

上述代码的输出是:
Output

我期望输出符合以下节点顺序:4 2 1

我不明白这一切是如何运作的。如果我错了,请纠正我。

4 个答案:

答案 0 :(得分:1)

它显示的输出是正确的,因为它首先遍历left sub-tree然后root然后right sub-tree

你不会得到4 2 1因为4离开了子树,然后它转到root 2然后转到2的右子树1}}。

当它过于正确时,子树根变为5,其左子树变为6。然后5然后到5的右子树那是7

1是根,因此如果不遍历左子树,则不会转到1

答案 1 :(得分:1)

要在Inorder中遍历二叉树,执行以下操作

(i) Traverse the left most subtree starting at the left external node, 
(ii) Visit the root, and 
(iii) Traverse the right subtree starting at the left external node.

现在删除节点,

(i) Traverse the left most subtree starting at the left external node,
(ii) delete the root, and 
(iii) Traverse the right subtree starting at the left external node.

答案 2 :(得分:1)

void delete_tree(tree *root)
{
    if(root==NULL)
        return;
    delete_tree(root->left);
    printf("Deleting %d node.\n",root->data);
    free(root);
    delete_tree(root->right);
}

这是一个inorder遍历,其中指针将首先指向最左边的节点,然后是root,然后是最右边的节点。由于4是最左边的节点,因此它已被打印,然后它将遍历到2。之后最右边的节点是5.自5以后有两个节点连接到它。它将再次迭代到大多数节点为6.因此它打印为4,2,6,5,7,3,9,8

答案 3 :(得分:1)

我最初将此作为评论发布,但看起来问这个问题的人对我的答案感到满意,所以我会在这里详细介绍一下。

当免费通话时,重要的是要注意确实实际上有什么免费的,否则会发生这样的事情。

  

C库函数void free(void * ptr)释放先前通过调用calloc,malloc或realloc分配的内存。

请注意,free函数不会更改指针的值,它只是将内存返回给OS,以便可以将其分配给另一个程序。因此,人们通常在自由调用后“清除”指针以避免访问另一个程序已更改的内存。

root = VOID;

上面的代码在释放之后不会清除根节点,因为内存仍然存在。因此,C代码能够转到该内存位置(操作系统已经收到)并对其进行修改。这是非常危险的行为,因为操作系统可以将此内存提供给另一个程序,然后您的程序可能会更改,从而导致明显的意外行为。对此的简单修复是在释放根节点之前删除正确的节点。