二叉查找树的查找、插入(建立在查找的基础上)较简单。
但删除节点需要花点心思,首先是分三种情况:
一、待删节点无左右孩子
二、待删节点只有一个孩子
三、待删节点两个孩子都有
而第三种情况又存在多种方法:
1、具体参考《数据结构》(C语言版)严蔚敏 230页,由于不符合本人习惯,略。
2、查找到节点的直接前驱,用前驱数据替换待删节点数据,然后删除前驱节点。
3、查找到节点的直接后继,用后继数据替换待删节点数据,然后删除后继节点。
所以这里又需要一个寻找前驱(后继)的方法,具体就是向左拐然后一直往右(或向右拐一直往左)。
代码如下:
为了符合自己的思维习惯,有些地方比较繁琐(比如判断节点是其父节点的左孩子还是右孩子)。
另外为了验证方便,多写了一个按层次遍历二叉树的方法。
#include <iostream>
#include <vector>
#include <queue>
using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::queue;
class Node
{
public:
int data;
Node *parent;
Node *lchild;
Node *rchild;
Node();
Node(int value);
};
Node::Node() : data(0), parent(NULL), lchild(NULL), rchild(NULL){}
Node::Node(int value) : data(value), parent(NULL), lchild(NULL), rchild(NULL){}
class CBST
{
private:
Node *T;
Node *Predecessor(Node *p); //返回某节点的前驱节点
public:
CBST(vector<int> src);
~CBST();
bool Search(int value, Node *tree, Node *&p);
void Insert(int value);
void Delete(int value);
void HierarchyShow(); //层序遍历展示
};
CBST::CBST(vector<int> src) : T(NULL)
{
vector<int>::iterator iter;
for(iter = src.begin(); iter != src.end(); ++iter)
{
Insert(*iter);
}
}
//若查找成功返回true,p指向所查找节点
//若失败返回false,p指向最后访问的节点
bool CBST::Search(int value, Node *tree, Node *&p)
{
if (NULL == tree)
{
return false;
}
else
{
p = tree;
if (tree->data < value)
{
Search(value, tree->rchild, p);
}
else if (tree->data > value)
{
Search(value, tree->lchild, p);
}
else //equal, found
{
return true;
}
}
}
void CBST::Insert(int value)
{
if (!T)
{
Node *q = new Node(value);
T = q;
}
else
{
Node *p = NULL;
if (!Search(value, T, p))
{
Node *q = new Node(value);
q->parent = p;
if (p->data < value)
{
p->rchild = q;
}
else //p->data > value
{
p->lchild = q;
}
}
else
{
cout<<"element already exist, insertion failed"<<endl;
}
}
}
//当待删节点左右孩子均不为空时,采用用直接前驱替换,删直接前驱节点的方法
void CBST::Delete(int value)
{
Node *p = NULL;
if (Search(value, T, p))
{
if ((NULL == p->lchild) && (NULL == p->rchild))
{
if (p->parent->lchild == p) p->parent->lchild = NULL;
else p->parent->rchild = NULL;
delete p;
p = NULL;
}
else if (NULL == p->lchild)
{
Node *temp = p;
if (p->parent->lchild == p) p->parent->lchild = p->rchild;
else p->parent->rchild = p->rchild;
delete temp;
temp = NULL;
}
else if (NULL == p->rchild)
{
Node *temp = p;
if (p->parent->lchild == p) p->parent->lchild = p->lchild;
else p->parent->rchild = p->lchild;
delete temp;
temp = NULL;
}
else //左右孩子均不为空
{
Node *pre = Predecessor(p);
int data = pre->data;
Delete(data);
p->data = data;
}
}
else
{
cout<<"the element do not exist, deletion failed"<<endl;
}
}
Node *CBST::Predecessor(Node *p)
{
if (!(p->lchild)) return p;
else
{
p = p->lchild;
while (p->rchild)
{
p = p->rchild;
}
return p;
}
}
void CBST::HierarchyShow()
{
if (NULL == T)
{
cout<<"empty"<<endl;
}
else
{
queue<Node *> nodeq;
cout<<T->data<<" ";
if (T->lchild) nodeq.push(T->lchild);
if (T->rchild) nodeq.push(T->rchild);
while (!nodeq.empty())
{
Node *p = nodeq.front();
nodeq.pop();
cout<<p->data<<" ";
if (p->lchild) nodeq.push(p->lchild);
if (p->rchild) nodeq.push(p->rchild);
}
cout<<endl;
}
}
CBST::~CBST()
{
//遍历释放节点空间,略
}
int main()
{
vector<int> src;
cout<<"请输入整形数组:";
int temp;
while (cin>>temp)
{
src.push_back(temp);
}
cin.clear();
cin.sync(); //需清缓冲,否则无法二次使用cin
CBST bst(src);
bst.HierarchyShow();
int i;
while(cin>>i)
{
vector<int> cpy(src);
CBST bcpy(cpy);
bcpy.Delete(i);
bcpy.HierarchyShow();
cout<<endl;
}
}