二叉搜索树的是是非非
上周把二叉搜索树的代码敲完后,参考了一部分的书上的代码。今天重新审阅调试这些代码时,发现了一些问题。至于我们的课本是什么呢,就不过多详述了,只能说呵呵
#include <iostream>
using namespace std;
template <class T>
class Node{ //结点类
public:
T element;
Node<T>* leftChild;
Node<T>* rightChild;
Node();//默认构造函数
Node(T value);//构造函数
~Node(){}//默认析构函数
};
template<class T>
Node<T>::Node() //默认构造
{
element = 0;
leftChild = rightChild = NULL;
}
template <class T>
Node<T>::Node(T value) //构造
{
element = value;
leftChild = rightChild = NULL;
}
template <class T>
class BSTree{
public:
Node<T>* root;
BSTree();//构造函数
~BSTree(){}//默认析构
void buildBSTree();//创建二叉树
Node<T>* search(Node<T>* root,T key);//二叉搜索树的查找
Node<T>* searchFather(Node<T>* root,Node<T>* k);//找爸爸
void InsertNode(const T& value);//二叉树的插入
void preOrder(Node<T>* root);//前序遍历二叉树
void delMerging(const T& value);//合并删除
void delCopying(const T& value);//复制删除
};
template<class T>
BSTree<T>::BSTree()
{
root = NULL;
}
template<class T>
void BSTree<T>::preOrder(Node<T>* root)
{
if (root != NULL)
{
cout<<root->element<<" ";
preOrder(root->leftChild);
preOrder(root->rightChild);
}
}
template <class T>
void BSTree<T>::buildBSTree() //插入创建二叉树
{
T t = NULL;
while(t != -1)
{
cin>>t;
if (t != -1)
InsertNode(t);
}
}
template <class T>
Node<T>* BSTree<T>::search(Node<T>* root,T key) //二叉树的查找
{
Node<T>* p = root;
if(root != NULL && (key != p->element))
{
if (key < p->element)
p = search(root->leftChild,key);
else
p = search(root->rightChild,key);
}
if (p != NULL)
return p;
else
return 0;
}
template <class T>
Node<T>* BSTree<T>::searchFather(Node<T>* root,Node<T>* k) //找某个节点的父亲
{
Node<T>* p = root;
if(root != NULL)
{
if (root->leftChild == k || root->rightChild == k)
return root;
else
{
searchFather(root->leftChild,k);
searchFather(root->rightChild,k);
}
}
}
template <class T>
void BSTree<T>::InsertNode(const T& value) //二叉搜索树的插入
{
Node<T>* p = root;
Node<T>* pre = NULL;
while(p != NULL)
{
pre = p;
if (p->element < value)
p = p->rightChild;
else
p = p->leftChild;
}
if (root == NULL) //考虑空树
root = new Node<T>(value);
else if (pre->element < value)
pre->rightChild = new Node<T>(value);
else
pre->leftChild = new Node<T>(value);
}
template <class T>
void BSTree<T>::delMerging(const T& value) //合并删除
{
Node<T>* node = search(root,value);
Node<T>* p = node;
Node<T>* pre = searchFather(root,node);
if (node != NULL)
{
if (node->leftChild == NULL && node->rightChild == NULL)
{
if (pre->leftChild == node)
pre->leftChild = NULL;
else
pre->rightChild = NULL;
}
else if (node->leftChild == NULL)//没有左子树
node = node->rightChild;
else if (node->rightChild == NULL)//没有右子树
node = node->leftChild;
else //左右子树都存在
{
p = node->leftChild;
while(p->rightChild != NULL)
p = p->rightChild;
p->rightChild = node->rightChild;
p = node;
if (pre->leftChild == node)
pre->leftChild = node->leftChild;
else
pre->rightChild = node->leftChild;
//node = node->leftChild; //该节点的左子树的根替代原节点
}
delete p; //释放空间
}
// cout<<node->element;
}
template <class T>
void BSTree<T>::delCopying(const T& value)//复制删除
{
Node<T>* node = search(root,value);
Node<T>* p = node;
Node<T>* temp;
Node<T>* pre = searchFather(root,node);
Node<T>* pr;
if (node->leftChild == NULL && node->rightChild == NULL)
{
if (pre->leftChild == node)
pre->leftChild = NULL;
else
pre->rightChild = NULL;
delete p;
}
else if (node->leftChild == NULL)//没有左子树
node = node->rightChild;
else if (node->rightChild == NULL)//没有右子树
node = node->leftChild;
else
{
pr = node;
p = node->leftChild;
while(p->rightChild != NULL)
{
pr = p;
p = p->rightChild;
}
node->element = p->element;
if (pr == node) /////////////////////这种情况会出现么?
{
temp = pr->leftChild;
pr->leftChild = p->leftChild;
p->leftChild = temp; /////////////////
}
else
pr->rightChild = p->leftChild;
}
}
int main()
{
BSTree<int> t;
t.buildBSTree();//插入建立二叉树
cout<<"删除之前:"<<endl;
t.preOrder(t.root);
if (t.search(t.root,10))
cout<<t.search(t.root,10)->element;//查找元素
else
cout<<"没有找到"<<endl;
// t.delMerging(4);
t.delCopying(4);
cout<<endl<<"删除4之后:"<<endl;
t.preOrder(t.root);
return 0;
}
这部分代码是经过一些修改的代码。书本上的一个很明显的bug是一个结点在删除后它的父亲节点的指针便成为一个野指针,在遍历过程中就会出现问题。而我的处理方式是添加一个“找爸爸”函数,通过要删除的结点来找到它的父亲的结点。所以说,特殊情况需要特殊代码来处理。其实这个代码依然不完善,存在bug,比如说在连续删除多个元素的过程中就会出现问题,目前还没有调试完毕,好吧,有空接着调试~

浙公网安备 33010602011771号