8
3 9
2 6 10
1 4 7
5
上面是1到10的二叉排序树。
如何实现二叉排序树的节点删除呢?假设我们删除结点6,先寻找前驱结点或者后继节点,6的前驱结点是5,后继是7,想象一下删除了结点6后,树该怎么变化?其实只要将6改成5,再将5的节点删除就OK了。
注意前驱或后继的度为1或者0。
(PS:这是从计蒜客学来的,不是打广告,侵权则删)
#include <iostream>
#include <cstdlib>
using namespace std;
class Node
{
public:
int data;
Node *lchild, *rchild, *father;
Node(int _data, Node*_father=NULL){
data = _data;
lchild = NULL;
rchild = NULL;
father = _father;
}
~Node(){
if(lchild != NULL)
delete lchild;
if(rchild != NULL)
delete rchild;
}
void myInsert(int value){
if(data == value)
return;
else if(value < data){
if(lchild == NULL)
lchild = new Node(value, this);
else
lchild->myInsert(value);
}
else{
if(rchild == NULL)
rchild = new Node(value, this);
else
rchild->myInsert(value);
}
}
Node *mySearch(int value){
if(data == value)
return this;
else if(value < data){
if(lchild == NULL)
return NULL;
else
lchild->mySearch(value);
}
else{
if(rchild == NULL)
return NULL;
else
rchild->mySearch(value);
}
}
/*寻找前驱*/
Node *predecessor(){
Node *temp = lchild;
while(temp!=NULL && temp->rchild!=NULL){
temp = temp->rchild;
}
return temp;
}
/*寻找后继*/
Node *successor(){
Node *temp = rchild;
while(temp!=NULL && temp->lchild!=NULL){
temp = temp->lchild;
}
return temp;
}
/*删除度为1或0的结点*/
void removeNode(Node *nodeOfdelete){
/*注意一定要将temp初始化为NULL*/
Node *temp = NULL;
if(nodeOfdelete->lchild != NULL){
temp = nodeOfdelete->lchild;
/*更新当前结点的子结点的父节点*/
temp->father = nodeOfdelete->father;
/*注意一定要将要删除节点的lchild和rchild置为NULL,注意Node类的析构函数*/
nodeOfdelete->lchild = NULL;
}
if(nodeOfdelete->rchild != NULL){
temp = nodeOfdelete->rchild;
temp->father = nodeOfdelete->father;
nodeOfdelete->rchild = NULL;
}
/*上面两个if只有一个成立,下面if对应的也只有一个成立*/
if(nodeOfdelete->father->lchild == nodeOfdelete)
nodeOfdelete->father->lchild = temp;
if(nodeOfdelete->father->rchild == nodeOfdelete)
nodeOfdelete->father->rchild = temp;
delete nodeOfdelete;
}
bool deleteNode(int value){
Node *currentNode, *nodeOfdelete;
currentNode = mySearch(value);
if(currentNode == NULL)
return false;
/*寻找前驱*/
if(currentNode->lchild != NULL)
nodeOfdelete = currentNode->predecessor();
/*或寻找后继*/
else if(currentNode->rchild != NULL)
nodeOfdelete = currentNode->successor();
/*要删除的结点是叶子结点*/
else
nodeOfdelete = currentNode;
/*更改结点的data值*/
currentNode->data = nodeOfdelete->data;
/*因为前驱和后继都是度为1的结点,如果不是前驱和后继那一定是叶子结点了,所以可以用remove函数进行删除*/
removeNode(nodeOfdelete);
return true;
}
void inOrder(){
if(lchild != NULL)
lchild->inOrder();
cout<<data<<" ";
if(rchild != NULL)
rchild->inOrder();
}
};
class BinaryTree
{
private:
Node *root;
public:
BinaryTree(){
root = NULL;
}
~BinaryTree(){
if(root != NULL)
delete root;
}
void myInsert(int value){
if(root == NULL)
root = new Node(value);
else
root->myInsert(value);
}
void mySearch(int value){
if(root->mySearch(value) != NULL)
cout << "存在" <<endl;
else
cout << "不存在" << endl;
}
void deleteNode(int value){
if(root->deleteNode(value))
cout << "删除成功" <<endl;
else
cout << "删除失败" <<endl;
}
void inOrder(){
if(root != NULL)
root->inOrder();
}
};
int main(){
BinaryTree binarytree;
int arr[] = {-111, 0, 22, 4, 3, 8, -2, -11, 123, 2333, 44, 9, 100};
for(int i=0; i<13; i++)
binarytree.myInsert(arr[i]);
binarytree.inOrder();
cout<<endl;
binarytree.mySearch(2333);
binarytree.mySearch(-2333);
binarytree.deleteNode(100);
binarytree.inOrder();
cout<<endl;
system("pause");
return 0;
}
如有疑问或错误,欢迎提出,谢谢