手写实现搜索二叉树:
- 树的节点定义:
class TreeNode
{
public:
TreeNode(int v) :value(v){};
TreeNode* left_son = NULL;
TreeNode* right_son = NULL;
TreeNode* p = NULL; //一定保存双亲的指针
int value = 0;
};
- 节点插入:
bool TreeInsert(TreeNode*& pRoot,int value)
{
TreeNode* pNew = new TreeNode(value);//待插入的节点
TreeNode* pParent = NULL;//父节点
TreeNode* pCur = pRoot;//子节点
while (pCur != NULL)
{
pParent = pCur;
if (pCur->value < value)
{
pCur = pCur->right_son;
}
else if (pCur->value>value)
{
pCur = pCur->left_son;
}
else
{
return false;
}
}
if (pParent == NULL)//空树
{
pRoot = pNew;
}
else if ( pParent->value<value )//插右边
{
pParent->right_son = pNew;
pNew->p = pParent;
}
else//插左边
{
pParent->left_son = pNew;
pNew->p = pParent;
}
return true;
}
- 最大值,最小值函数
TreeNode* TreeMax(TreeNode* pRoot)
{
while (pRoot!=NULL&&pRoot->right_son!=NULL)
{
pRoot = pRoot->right_son;
}
return pRoot;
}
TreeNode* TreeMin(TreeNode* pRoot)
{
while (pRoot!=NULL&&pRoot->left_son!=NULL)
{
pRoot = pRoot->left_son;
}
return pRoot;
}
- 前驱、后继函数
TreeNode* Successor(TreeNode* pRoot)
{
/* 寻找节点的后继节点 方法一:中序遍历,后继即 该节点输出的后一个节点 方法二:若当前节点有右孩子,则后继为右孩子子树的最小节点 若当前节点无右孩子,则后继为其最底层的祖先,条件是该结点位于此祖先的左子树 */
if (pRoot==NULL)
{
return pRoot;
}
if (pRoot->right_son != NULL)// 当前节点有右孩子
{
return TreeMin(pRoot->right_son);
}
TreeNode* pChild = pRoot;
TreeNode* pParent = pChild->p;
while (pParent != NULL&&pParent->right_son == pChild)//当前节点无右孩子,寻找满足要求的最底层祖先
{
pChild = pParent;
pParent = pParent->p;
}
return pParent;
}
TreeNode* Processor(TreeNode* pRoot)
{
/* 寻找节点的前驱节点 若当前节点有左孩子,则前驱为左孩子子树的最大节点 若当前节点无左孩子,则后继为其最底层的祖先,条件是该结点位于此祖先的右子树 */
if (pRoot == NULL)
{
return pRoot;
}
if (pRoot->left_son != NULL)//有左孩子
{
return TreeMax(pRoot->left_son);
}
TreeNode* pChild = pRoot;
TreeNode* pParent = pChild->p;
while (pParent != NULL&&pParent->left_son == pChild)//无左孩子,寻找满足要求的最底层祖先
{
pChild = pParent;
pParent = pParent->p;
}
return pParent;
}
- 替换函数,使用一棵树接管另一棵树的双亲
bool TransPlant(TreeNode *& pRoot,TreeNode* pOld,TreeNode* pNew)
{
/* 使用一棵树接管另一棵树的双亲 */
if (pRoot == NULL||pOld == NULL)//旧子树为空
{
return false;
}
//调整父节点的指针
if (pOld->p == NULL)//父节点为空:替换了根节点
{
pRoot = pNew;
}
else
{
if (pOld == pOld->p->left_son)
{
pOld->p->left_son = pNew;
}
else
{
pOld->p->right_son = pNew;
}
}
//调整指向父节点的指针
if (pNew != NULL)//新子树不为空
{
pNew->p = pOld->p;
}
return true;
}
- 删除节点
void TreeDelete(TreeNode*& pRoot,TreeNode* pDelete)
{
/* 删除指定节点 */
if (pRoot == NULL || pDelete == NULL)
return;
if (pDelete->left_son == NULL)//没有孩子或者只有一个孩子,直接将孩子提上来
{
TransPlant(pRoot,pDelete,pDelete->right_son);
}
else if (pDelete->right_son == NULL)
{
TransPlant(pRoot,pDelete->left_son);
}
else//同时有两个孩子时
{
TreeNode* successor = TreeMin(pDelete->right_son);//寻找后继,后继一定没有左孩子节点
if (successor->p != pDelete)//后继不是被删除节点的右孩子节点
{
TransPlant(pRoot,successor,successor->right_son);//删除后继节点
successor->right_son = pDelete->right_son;//将后继提到被删除节点右孩子位置上:接管被删除节点的右孩子
successor->right_son->p = successor;
}
TransPlant(pRoot,successor);//后继接管被删节点的双亲
successor->left_son = pDelete->left_son;//后继接管被删节点的左孩子
successor->left_son->p = successor;
}
}
void TreePrint(TreeNode* pRoot)
{
if (pRoot == NULL)
{
return;
}
TreePrint(pRoot->left_son);
cout << pRoot->value << " ";
TreePrint(pRoot->right_son);
}
int main()
{
TreeNode* pRoot(NULL);
TreeInsert(pRoot,4);
TreeInsert(pRoot,1);
TreeInsert(pRoot,9);
TreeInsert(pRoot,2);
TreeInsert(pRoot,8);
TreeInsert(pRoot,3);
TreeInsert(pRoot,6);
TreePrint(pRoot);
cout << endl;
TreeDelete(pRoot,pRoot);
TreePrint(pRoot);
return 0;
}