1. 程式人生 > >關於刪除二叉樹子樹的兩種操作

關於刪除二叉樹子樹的兩種操作

/*一、
名稱:刪除二叉樹中以x為根的子樹
說明:此程式的大部分內容,註釋都解釋的較為詳細了。在這裡需要提及一點的是此處遞迴函式flag傳遞的不是上篇中講的引用,而是普通的變數,因為在向下傳遞引數(當前結點是否是x的資訊)的過程中只要傳遞給對應的子樹,並不需要傳遞給整個樹的結點。在下一篇會做個關於遞迴傳遞引數的總結。*/
//遞迴刪除二叉樹中以x為根的子樹,(flag為標誌)
int DelRoot_x(BiTree &T, int x,int flag)
{
    if(T == NULL)
        return 0;
    else
    {
        if(T->data == x)    //如果當前節點的值為x,則更改標誌位,在下面將向遞迴子函式中傳遞flag值
        {
            flag = 1;
        }
        int lef_ret = DelRoot_x(T->lchild,x,flag);  //遞迴左子樹,lef_ret為從左子樹中返回的資訊
        int rig_ret = DelRoot_x(T->rchild,x,flag);  //遞迴右子樹,rig_ret為從右子樹中返回的資訊
        if(1 == flag)       //如果標誌為1,說明其祖父結點中有x,也就是說當前結點需要刪除
        {
            if(T->data == x)    //如果是x結點,則需要向上層結點傳遞資訊,以便其父節點將對應的指標域賦空
                return 1;
            delete T;
        }
        else
        {
             if(1 == lef_ret)    //從子結點接受收的資訊,即如果其子結點為x,需要將其指標域賦空
                T->lchild = NULL;
            if(1 == rig_ret )   //從子結點接受收的資訊,即如果其子結點為x,需要將其指標域賦空
                T->rchild = NULL;
        }
    }
    return  0;
}

/* 二、同時傳遞父節點與子節點,因為是中序線索二叉樹,因此要判斷一下ltag和rtag的值,若是普通二叉樹,刪掉即可。
void Tree::deleteNodeTree(char data,struct node* node,struct node* pre)
{
	if (node != NULL)
	{
		if (node->data == data && node != getRoot())//如果刪除的不是根節點
		{ 
			if (pre->leftChild == node) //防止刪除節點的父節點的指標懸空
				pre->leftChild = NULL;
			else if (pre->rightChild == node) 
				pre->rightChild = NULL;
			destroyTree(node);
			return;
		}
		else if (node->data == data)
		{
			destroyTree(node);
			return;
		}
		if(node->ltag == 0)
			deleteNodeTree(data,node->leftChild,node);
		if(node->rtag == 0)
			deleteNodeTree(data,node->rightChild,node);
	}
}
void Tree::destroyTree(struct node* node)
{
	if (node == NULL)
	{
		return;
	}
	if (node->leftChild != NULL&&node->ltag == 0)
	{
		destroyTree(node->leftChild);
	}
	if (node->rightChild != NULL&&node->rtag == 0)
	{
		destroyTree(node->rightChild);
	}
	delete node;
	node = NULL;
	return;
}