二叉排序树(搜索数)C++实现代码

自己用C++写的二叉排序树(搜索数),具有初始化、增、删、查、中序遍历的功能。由于二叉搜索树的中序遍历是一个升序的序列,这也是二叉搜索树的特征之一,而前序遍历和后续遍历意义不大,而且与中序遍历代码原理差不多,只需稍作改动,所以就没写后续遍历和前序遍历。不足之处还请大家多多指出

类头文件

#ifndef BinSearchTree_H
#define	BinSearchTree_H
#include <iostream>
using namespace std;

class BinNode
{

public:
	friend class BinTree;
	BinNode() {}
	BinNode(int data)
	{
		m_data = data;
		m_id = -1;
		m_parent = NULL;
		m_leftchild = NULL;
		m_rightchild = NULL;
	}
	bool insertNode(int data);		//插入数据为data的结点
	BinNode* getMaxNode();		//获取子树的最大结点
	BinNode* getMinNode();		//获取子树的最小结点
	BinNode* getPreNode();		//获取前驱结点,也即当前结点的左子树中最大的结点
	BinNode* getNextNode();		//获取后继结点,也即当前结点的右子树中的最小的结点
	bool deleteNode();		//删除当前结点
	BinNode* searchNode(int data);		//在子树中搜索数据为data的结点是否存在
	bool inOrderTraverse();			//中序遍历
	void clean();		//删除子树的所有结点
	int get_m_data() 
	{ 
		if (this != NULL)
			return m_data;
		else return -1;
	}
private:
	int m_data;
	BinNode* m_parent;
	BinNode* m_leftchild;
	BinNode* m_rightchild;
	int m_id;
};

class BinTree
{
public:
	BinTree()
	{
		size = 0;
		root = NULL;
	}
	~BinTree()
	{
		cout << "**********~BinTree()*******" << endl;
		cleanTree();
	}
	void insertTree(int* arry,int size);		//将序列中的size个数据插入到当前树中或者用该序列生成一棵二叉搜索树
	void insertTree(int data);		//插入数据为data的结点
	bool deleteTreeNode(int data);			//删除数据为data的结点
	BinNode* searchTree(int data);		//搜索树中数据为data的结点是否存在
	BinNode* getPreTreeNode(int data);	//获取数据为data的结点的前驱结点
	BinNode* getNextTreeNode(int data);	//获取数据为data的结点的后继结点
	BinNode* getTreeMaxNode();		//获取树的最大结点
	BinNode* getTreeMinNode();		//获取树的最小结点
	bool inOrderTree();				//中序遍历
	void cleanTree();		//清空树,将其变为一颗空树
private:
	BinNode* root;
	int size;   //树的所有结点个数
};
#endif 

.cpp文件,类成员函数实现

#include <iostream>
#include "BinSearchTree.h"
using namespace std;

void BinTree::insertTree(int* arry,int size)	//使用初始序列构造一棵二叉搜索树
{
	int i = 0;
	if (root == NULL)
	{
		root = new BinNode;
		root->m_id = 0;
		root->m_data = *arry;
		root->m_parent = NULL;
		root->m_leftchild = NULL;
		root->m_rightchild = NULL;
		i++;
	}
	while(i<size)
	{
		root->insertNode(arry[i]);
		i++;
	}
}

void BinTree::insertTree(int data)
{
	if (root == NULL)
	{
		root = new BinNode;
		root->m_id = 0;
		root->m_data = data;
		root->m_parent = NULL;
		root->m_leftchild = NULL;
		root->m_rightchild = NULL;
	}
	else 
		root->insertNode(data);
}

bool BinTree::deleteTreeNode(int data)
{
	BinNode*  temp= this->searchTree(data);		//找到需要删除的结点
	if (temp != NULL)
	{
		temp->deleteNode();
		return true;
	}
	return false;
}

BinNode* BinTree::searchTree(int data)
{
	if (root == NULL)
		return NULL;
	else return root->searchNode(data);
}

bool BinTree::inOrderTree()
{
	if (root == NULL)
		return false;
	else
	{
		root->inOrderTraverse();
		cout << endl;
		return true;
	}
}

BinNode* BinTree::getPreTreeNode(int data)
{
	BinNode* temp = searchTree(data);
	if (temp == NULL)
		return NULL;
	else return temp->getPreNode();
}

BinNode* BinTree::getNextTreeNode(int data)
{
	BinNode* temp = searchTree(data);
	if (temp == NULL)
		return NULL;
	else return temp->getNextNode();
}

BinNode* BinTree::getTreeMaxNode()
{
	if (root != NULL)
		return root->getMaxNode();
	else return NULL;
}

BinNode* BinTree::getTreeMinNode()
{
	if (root != NULL)
		return root->getMinNode();
	else return NULL;
}

void BinTree::cleanTree()
{
	if (root == NULL)
		return;
	root->clean();
	root = NULL;
}


bool BinNode::insertNode(int data)
{
	if (data >= this->m_data)			//大的插入到右子树
	{
		if (this->m_rightchild == NULL)					//如果右孩子为空,则直接作为右孩子插入
		{
			this->m_rightchild = new BinNode;
			this->m_rightchild->m_parent = this;
			this->m_rightchild->m_data = data;
			this->m_rightchild->m_id = this->m_id * 2 + 2;
			this->m_rightchild->m_leftchild = NULL;
			this->m_rightchild->m_rightchild = NULL;
		}
		else			//如果右孩子不为空,则递归插入函数,直到作为叶子结点插入
		{
			this->m_rightchild->insertNode(data);
		}
		return true;
	}
	else								//小的插入到左子树
	{
		if (this->m_leftchild == NULL)			//如果左孩子为空,则直接作为左孩子插入
		{
			this->m_leftchild = new BinNode;
			this->m_leftchild->m_parent = this;
			this->m_leftchild->m_data = data;
			this->m_leftchild->m_id = this->m_id * 2 + 1;
			this->m_leftchild->m_leftchild = NULL;
			this->m_leftchild->m_rightchild = NULL;
		}
		else			//如果左孩子不为空,则递归插入函数,直到作为叶子结点插入
		{
			this->m_leftchild->insertNode(data);
		}
		return true;
	}
}

BinNode* BinNode::getMinNode()
{
	if (this->m_leftchild == NULL)		//没有左孩子,说明自己就是最小的结点
		return this;
	else		//如果左子树存在,则递归左子树,在左子树中找最小的结点
	{
		return this->m_leftchild->getMinNode();
	}
}
BinNode* BinNode::getMaxNode()
{
	if (this->m_rightchild == NULL)		//没有右孩子,说明自己就是最大的结点
		return this;
	else		//如果右子树存在,则递归右子树,在右子树中找最大的结点
	{
		return this->m_rightchild->getMaxNode();
	}
}

BinNode* BinNode::getPreNode()
{
	if (this->m_leftchild == NULL)		//左孩子为空,说明没有前驱
		return NULL;
	return this->m_leftchild->getMaxNode();				//左子树中的最大结点即为前驱
}

BinNode* BinNode::getNextNode()
{
	if (this->m_rightchild == NULL)
		return NULL;		//右孩子为空,说明没有后继
	return this->m_rightchild->getMinNode();		//右子树中的最小结点即为后继
}

BinNode* BinNode::searchNode(int data)
{
	if (this->m_data == data)
		return this;
	else if (data < this->m_data)			//小的在左边
	{
		if (this->m_leftchild == NULL)		//左边已经到底
			return NULL;
		else return this->m_leftchild->searchNode(data);
	}	
	else		//大于等于的在右边
	{
		if (this->m_rightchild == NULL)		//右边已经到底
			return NULL;
		else return this->m_rightchild->searchNode(data);
	}	
}

bool BinNode::inOrderTraverse()
{
	if (this->m_leftchild != NULL)
		this->m_leftchild->inOrderTraverse();
	cout << this->m_data << " ";
	if (this->m_rightchild != NULL)
		this->m_rightchild->inOrderTraverse();
	return true;
}

bool BinNode::deleteNode()
{
	/****************第一种情况,该结点为叶子结点,没有左右孩子,则直接删除结点****************/
	if (this->m_leftchild == NULL && this->m_rightchild == NULL)			
	{
		if (this->m_parent->m_leftchild == this)				//改结点是左叶子
		{
			this->m_parent->m_leftchild = NULL;
			delete this;
			return true;
		}
		else							//该结点是右叶子
		{
			this->m_parent->m_rightchild = NULL;
			delete this;
			return true;
		}
	}

	/*********第二种情况,该结点只有左孩子或者只有右孩子,则用该结点的子树代替该结点********************/
	else if (this->m_leftchild != NULL&& this->m_rightchild == NULL)						//只有左孩子			
	{
		if (this->m_parent->m_leftchild == this)     //该结点是其父结点的左孩子
		{
			this->m_parent->m_leftchild = this->m_leftchild;		//其父结点的左孩子变为其左子节点
			this->m_leftchild->m_parent = this->m_parent;			//千万不要忘记其子结点的父结点也要该变
			delete this;
		}
		else		//该结点是其父结点的右孩子
		{
			this->m_parent->m_rightchild = this->m_leftchild;		//其父结点的右孩子变为其左子节点
			this->m_leftchild->m_parent = this->m_parent;			//千万不要忘记其子结点的父结点也要该变
			delete this;
		}
	}
	else if (this->m_leftchild == NULL && this->m_rightchild != NULL)						//只有右孩子	
	{

		if (this->m_parent->m_leftchild == this)     //该结点是其父结点的左孩子
		{
			this->m_parent->m_leftchild = this->m_rightchild;		//其父结点的左孩子变为其左子节点
			this->m_rightchild->m_parent = this->m_parent;			//千万不要忘记其子结点的父结点也要该变
			delete this;
		}
		else		//该结点是其父结点的右孩子
		{
			this->m_parent->m_rightchild = this->m_rightchild;		//其父结点的右孩子变为其左子节点
			this->m_rightchild->m_parent = this->m_parent;			//千万不要忘记其子结点的父结点也要该变
			delete this;
		}
	}

	/**********最后一种情况,该结点既有左孩子,又有右孩子,则找到该结点的后继代替该结点,该结点后继结点的子树上移(后继结点如果有子树,则一定是右子树)*****************/
	/****后继替换需要删除的结点时,直接用后继结点的数据代替需要删除结点的数据即可。然后将后继结点的子树替换后继结点,最后删除后继结点********/
	else
	{
		BinNode* thisNext= this->getNextNode();					//获取后继结点

		/****************用后继结点代替需要删除的结点this**********************************/
		this->m_data = thisNext->m_data;			//由于删除结点位置的孩子和父亲没有发生改变,所以直接用后继结点的数据替换删除结点的数据即可。否则如果用整个后继结点的内存替换删除结点,还要还原替换后结点的父亲和孩子

		/***************用后继结点的子树代替后继结点的位置******************/
		if (thisNext->m_parent->m_leftchild == thisNext)			//如果后继是其父结点的左子树
		{
			if (thisNext->m_rightchild == NULL)		//后继没有右孩子,也即没有孩子
			{
				thisNext->m_parent->m_leftchild = NULL;
			}
			else
			{
				thisNext->m_parent->m_leftchild = thisNext->m_rightchild;			//父亲孩子结点改变
				thisNext->m_rightchild->m_parent = thisNext->m_parent;				//孩子结点的父亲改变
			}
		}
		else	//后继是其父结点的右子树
		{
			if (thisNext->m_rightchild == NULL)		//后继没有右孩子,也即没有孩子
			{
				thisNext->m_parent->m_rightchild =NULL;
			}
			else
			{
				thisNext->m_parent->m_rightchild = thisNext->m_rightchild;			//父亲孩子结点改变
				thisNext->m_rightchild->m_parent = thisNext->m_parent;				//孩子结点的父亲改变
			}
		}
		delete thisNext;		//由于后继结点的数据已经替换到了删除的结点,此时就可以将后继结点的内存空间删除
	}
}

void BinNode::clean()
{
	if (this->m_leftchild != NULL)
	{
		this->m_leftchild->clean();		//如果左子树存在,则递归删除左子树

	}

	if (this->m_rightchild != NULL)
	{
		this->m_rightchild->clean();	//如果右子树存在,则递归删除右子树
	}

	/***********此时说明this没有左右子树,是叶子结点,使this的父节点指向空,此叶子结点就从树上删除了,但是this本身的空间还未删除,最后还需要再删除this本身的内存********************/
	/***********注意是this的父节点指向空,this才从树上断开。而不是this指向空。仅仅是this指向空,则this的父结点还是指向this,this结点并没有从树上撤下来***********************/
	/***********所以从树上撤下this结点的关键是this的父节点指向空。********************************/
	if (this->m_parent != NULL)			//必须加这句,因为如果是根结点,其m_parent为空时,NULL->m_leftchild访问权限错误,因为NULL是不能访问的
	{
		if (this->m_parent->m_leftchild == this)
		{
			this->m_parent->m_leftchild = NULL;
		}
		if (this->m_parent->m_rightchild == this)
		{
			this->m_parent->m_rightchild = NULL;
		}
	}
	cout << "delete " << this->m_data << endl;
	delete this;			//上面的步骤只是讲this从树上撤下来,但是this本身的内存并没有释放,此时才释放
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>