一、二叉搜索树的基本概念、难点
前驱:大于该结点关键字的最小关键字的结点
后继:小于该结点关键字的最大关键字的结点
删除操作
分为三种情况,都调用了结点替换函数;较复杂的情况为要删除的结点有两个孩子,要进行两次替换,第一次将该结点的右子树中的最小值与该结点的右孩子替换,第二次将该结点与该结点的右子树替换。最后都会调用delete释放内存。
二、完整源代码
#include <iostream>
using namespace std;
typedef struct __tree
{
int data;
__tree* left;
__tree* right;
__tree* parent;
}tree, *pTree;
//打印
void PrintTree(pTree pT);
//查找
pTree Search(pTree pT, int x);
pTree LoopSearch(pTree pT, int x);//查找的循环实现
//最大结点、最小结点
pTree MaxLeaf(pTree root);
pTree MinLeaf(pTree root);
//前驱、后继
pTree TreeSuccessor(pTree pT);
pTree TreePresuccessor(pTree pT);
//插入
void TreeInsert(pTree& pT, int x);
//将u替换为v
void Transplant(pTree& pT, pTree u, pTree v);
//删除结点
void TreeDelete(pTree pT, pTree& z);
int main()
{
pTree p = NULL;
int array[9] = {12, 5, 2, 9, 18, 15, 19, 17, 13};
for (int i = 0; i < 9; ++ i)
TreeInsert(p, array[i]);
// cout << Search(p, 19)->data << endl;
// cout << TreePresuccessor(p)->data << endl;
// cout << TreeSuccessor(p)->data << endl;
// cout << MaxLeaf(p)->data << endl;
// cout << MinLeaf(p)->data << endl;
// PrintTree(p);
pTree pDelete = Search(p, 5);
TreeDelete(p, pDelete);
PrintTree(p);
return 0;
}
void PrintTree(pTree pT)
{
if (pT != NULL)
{
PrintTree(pT->left);
PrintTree(pT->right);
printf("%d\n", pT->data);
}
}
pTree Search(pTree pT, int x)
{
if (pT->data == x || pT == NULL)
return pT;
if (pT->data > x)
return Search(pT->left, x);
else
return Search(pT->right,x);
}
pTree LoopSearch(pTree pT, int x)
{
while (pT->data != x && pT != NULL)
if (pT->data > x)
pT = pT->left;
else
pT = pT->right;
return pT;
}
pTree MaxLeaf(pTree root)
{
while (root->right != NULL)
root = root->right;
return root;
}
pTree MinLeaf(pTree root)
{
while (root->left != NULL)
root = root->left;
return root;
}
pTree TreeSuccessor(pTree pT)
{
if (pT->right != NULL)
return MinLeaf(pT->right);
pTree pTmp = pT->parent;
while (pTmp != NULL && pT == pTmp->right)
{
pT = pTmp;
pTmp = pTmp->parent;
}
return pTmp;
}
pTree TreePresuccessor(pTree pT)
{
if (pT->left != NULL)
return MaxLeaf(pT->left);
pTree pTmp = pT->parent;
while (pTmp != NULL && pT == pTmp->left)
{
pT = pTmp;
pTmp = pTmp->parent;
}
return pTmp;
}
void TreeInsert(pTree& pT, int x)
{
pTree pTmp = new tree;
pTmp->left = pTmp->right = NULL;
pTmp->data = x;
pTree pFind = pT;//遍历指针
pTree pPos = NULL;//要插入的父指针
while (pFind != NULL)
{
pPos = pFind;
if (pFind->data > x)
pFind = pFind->left;
else
pFind = pFind->right;
}
pTmp->parent = pPos;
if (pT == NULL)
pT = pTmp;
else if (pPos->data > x)
pPos->left = pTmp;
else
pPos->right = pTmp;
}
void Transplant(pTree& pT, pTree u, pTree v)
{
if (u->parent == NULL)
pT = v;
else if (u == u->parent->left)
u->parent->left = v;
else
u->parent->right = v;
if (v != NULL)
v->parent = u->parent;
}
void TreeDelete(pTree pT, pTree& z)
{
if (z->left == NULL)
Transplant(pT, z, z->right);
else if (z->right == NULL)
Transplant(pT, z, z->left);
else
{
pTree y = MinLeaf(z->right);
if (y->parent != z)
{
Transplant(pT, y, y->right);
y->right = z->right;
y->right->parent = y;
}
Transplant(pT, z, y);
y->left = z->left;
y->left->parent = y;
}
delete z;
z = NULL;
}