CatCoding

指针指针

2010-07-20

今天由一个函数加深了对指针的理解,是这么一个函数:

void BST_Delete(BITREE y) //删除节点 y
{
    if (y->lch==NULL && y->rch==NULL && y->p)
    {
        if(y==(y->p)->lch) (y->p)->lch=NULL;
        else (y->p)->rch=NULL;
    }
    else if (y->rch==NULL && y->p)
    {
        if(y==y->p->lch) y->p->lch=y->lch;
        else y->p->rch=y->lch;
    }
    else if (y->lch==NULL && y->p){
        if(y==y->p->lch) y->p->lch=y->rch;
        else y->p->rch=y->rch;
    }
    else    {
        BITREE t=BST_Successor(y);
        y->data=t->data;
        BST_Delete(t);
        y=t;//y=NULL

    }
    free(y);
}

在最后一个 else 内,如果二叉搜索树中有左右孩子,那么找这个删除节点的后继,把内容互换,然后删除后继 节点,因为后继节点一定只有一个孩子或者没有孩子。最后只有一个 free() 操作其实是为了代码简洁,可以把前面每一个 else if 后面加一个 free,最后不写 free() 操作。但是这么写运行起来会有问题,y=t,就是所指向的地址相同,但是因为是 递归操作,t 指向的地址在调用 BST_Delete(t) 的时候已经被 free 掉了,所以如果再删除一次就会 出现内存错误,修改方法是 y=NULL,或者修改函数参数,用指针引用的形式 void BST_Delete( BITREE& y),然后再在 free(y) 后面增加一句 y=NULL。以前以为两次调用 free(p) 是不会出现问题的,free() 在释放掉 p 指向的内存以后,会 自动将 p 赋值为 NULL,其实没有这部分操作。

前些天还看到一个面试题目,malloc 申请的空间用 delete 删除会有什么问题?一般来说没有问题,内存会释放掉,而且即使是有析构函数的对象指针,用 delete 删除的时候同样会调用析构函数。这说明 c++ 的 delete 操作其实是在 c 的基础增加了一些操作,先调用析构函数,然后释放空间。良好的编程风格 就是 free/malloc,new/delete 一一对应,甚至不要出现一次调用,多次释放,像上面那样的因为递归 而产生的多次释放并不是很好发现

公号同步更新,欢迎关注👻