二叉搜索树的是是非非

  上周把二叉搜索树的代码敲完后,参考了一部分的书上的代码。今天重新审阅调试这些代码时,发现了一些问题。至于我们的课本是什么呢,就不过多详述了,只能说呵呵

 

#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,比如说在连续删除多个元素的过程中就会出现问题,目前还没有调试完毕,好吧,有空接着调试~

posted @ 2013-11-21 20:00  too_young  阅读(138)  评论(0)    收藏  举报