C删除二叉树后的无限循环

时间:2017-02-20 07:25:56

标签: c binary-tree infinite-loop

我实现了一个删除树节点及其子树的函数,如下所示:

void DeleteTree(BTreeNode * bt){
    if(bt == NULL)
        return;

    DeleteTree(bt->left);
    DeleteTree(bt->right);

    printf("del tree data: %d \n", bt->data);
    free(bt);
}

然后我有另一个遍历树的函数:

void PreorderTraverse(BTreeNode * bt, VisitFuncPtr action){
    if(bt == NULL)
        return;

    action(bt->data);
    PreorderTraverse(bt->left, action);
    PreorderTraverse(bt->right, action);
}

这里,参数" action"是一个函数指针,它将节点的数据作为参数并具有void返回类型,用于调用另一个打印节点数据的函数。

这是我的主要内容:

#include <stdio.h>
#include <stdlib.h>
#include "BinaryTree.h"

void ShowIntData(int data){
    printf("%d ", data);
}

int main(){
    BTreeNode * bt1 = MakeBTreeNode();
    BTreeNode * bt2 = MakeBTreeNode();
    BTreeNode * bt3 = MakeBTreeNode();
    BTreeNode * bt4 = MakeBTreeNode();
    BTreeNode * bt5 = MakeBTreeNode();
    BTreeNode * bt6 = MakeBTreeNode();

    SetData(bt1, 1);
    SetData(bt2, 2);
    SetData(bt3, 3);
    SetData(bt4, 4);
    SetData(bt5, 5);
    SetData(bt6, 6);

    MakeLeftSubTree(bt1, bt2);
    MakeRightSubTree(bt1, bt3);
    MakeLeftSubTree(bt2, bt4);
    MakeRightSubTree(bt2, bt5);
    MakeRightSubTree(bt3, bt6);

    PreorderTraverse(bt1, ShowIntData);
    printf("\n");
    DeleteTree(bt3);
    PreorderTraverse(bt1, ShowIntData);

    return 0;
}

问题是,在DeleteTree之后,再次调用PreorderTraverse时,程序会陷入无限循环,打印出一些垃圾值。你能解释一下为什么会这样吗?供您参考,我将在下面向您展示BinaryTree.h和BinaryTree.c供您参考。

BinaryTree.h

#ifndef __BINARY_TREE_H__
#define __BINARY_TREE_H__

typedef int BTData;

typedef struct _bTreeNode{
    BTData data;
    struct _bTreeNode * left;
    struct _bTreeNode * right;
} BTreeNode;

BTreeNode * MakeBTreeNode(void);
BTData GetData(BTreeNode * bt);
void SetData(BTreeNode * bt, BTData data);

BTreeNode * GetLeftSubTree(BTreeNode * bt);
BTreeNode * GetRightSubTree(BTreeNode * bt);

void MakeLeftSubTree(BTreeNode * main, BTreeNode * sub);
void MakeRightSubTree(BTreeNode * main, BTreeNode * sub);

typedef void VisitFuncPtr(BTData data);

void PreorderTraverse(BTreeNode * bt, VisitFuncPtr action);
void InorderTraverse(BTreeNode * bt, VisitFuncPtr action);
void PostorderTraverse(BTreeNode * bt, VisitFuncPtr action);

void DeleteTree(BTreeNode * bt);

#endif // __BINARY_TREE_H__

BinaryTree.c

#include <stdio.h>
#include <stdlib.h>
#include "BinaryTree.h"

BTreeNode * MakeBTreeNode(void){
    BTreeNode * nd = (BTreeNode*)malloc(sizeof(BTreeNode));

    nd->left = NULL;
    nd->right = NULL;
    return nd;
}

BTData GetData(BTreeNode * bt){
    return bt->data;
}

void SetData(BTreeNode * bt, BTData data){
    bt->data = data;
}

BTreeNode * GetLeftSubTree(BTreeNode * bt){
    return bt->left;
}

BTreeNode * GetRightSubTree(BTreeNode * bt){
    return bt->right;
}

void MakeLeftSubTree(BTreeNode * main, BTreeNode * sub){
    if(main->left != NULL)
        free(main->left);

    main->left = sub;
}

void MakeRightSubTree(BTreeNode * main, BTreeNode * sub){
    if(main->right != NULL)
        (main->right);

    main->right = sub;
}

void PreorderTraverse(BTreeNode * bt, VisitFuncPtr action){
    if(bt == NULL)
        return;

    action(bt->data);
    PreorderTraverse(bt->left, action);
    PreorderTraverse(bt->right, action);
}

void DeleteTree(BTreeNode * bt){
    if(bt == NULL)
        return;

    DeleteTree(bt->left);
    DeleteTree(bt->right);

    printf("del tree data: %d \n", bt->data);
    free(bt);
}

非常感谢。

2 个答案:

答案 0 :(得分:3)

free未设置指向NULL的指针。

删除后调用PreorderTraverse调用Undefined Behavior ,因为该函数将尝试取消引用释放的动态内存。

答案 1 :(得分:0)

BinaryTree.c上的第38行(函数MakeRightSubTree)应为

free(main->right);

而不是

(main->right);