二叉搜索树的c++类模板封装实现

二叉搜索树:一个近似二分搜索的数据结构跳表有点像,平衡二叉树可以靠旋转操作维护自平衡性,解决退化为链表问题;跳表通过随机函数进行上层节点增删,统计意义上维护平衡性。

c++实现代码:

Binary_SearchTree.h

hpp文件 实现类的成员函数

测试文件

测试运行结果

缺点:


概念:

二叉搜索树:二叉搜索树是由二叉树来组织的,树中每一个子树的根节点key值都大于左树的key值而小于右子树的key值。

                   二叉搜索树的中序遍历key值恰好是从小到达排序。查询二叉树、MinMum、MaxMum、Insert和delete等操作时间复杂                    度为O(h); h为树的高度log2(n);

c++实现代码:

              头文件,树节点和树 类的定义

Binary_SearchTree.h

   

#ifndef _BINARY_SEARCHTREE
#define  _BINARY_SEARCHTREE

template<typename T>//定义Element类,便于外部调用函数更改数据类型
class Element
{
public:
	T key;//便于在节点中随时加入数据
	char name;

};

template<typename T> class BST;//BST模板类的声明

template<typename T>
class BSTNode
{
	friend class BST<T>;//友元类声明 BST二叉树要访问节点私有元素
public:
	Element<T> getElement();
	private:
		Element<T> data;
	    BSTNode *leftChild;
	    BSTNode *rightChild;
		void display(int i);//递归展示当前节点信息
	
};

template<typename T>//搜索二叉树模板类
class BST
{
public:
	BST(BSTNode<T>*init = 0);
	bool BST_insert(const Element<T> &node);//插入元素
	BSTNode<T>* BST_Search(const Element<T>&node);//递归搜索
	BSTNode<T>* BST_Search(BSTNode<T>*,const Element<T>&);

	BSTNode<T>*BST_Search_Iterator(const Element<T>&);//迭代搜索
	bool Delete_Node(const Element<T>&node);//删除节点
	BSTNode<T>*MinMum();//树的key最大节点
	BSTNode<T>*MaxMum();//树的key最小节点

	void midOrder();//中序遍历
	void midOrder(BSTNode<T>*root);

	void display();//递归左右子树展示当前树所有节点信息
	~BST();

private:
	BSTNode<T> *root;

};

#endif

hpp文件 实现类的成员函数

#include"Binary_SearchTree.h"
#include"iostream"
using namespace std;
//节点的成员函数

//节点内容获取
template<typename T>
void BSTNode<T>::display(int i)
{
	cout << "position: " << i << "  data.Key:" << data.key << " value:" << data.name << endl;
	if (leftChild)
		leftChild->display(2 * i);
	if (rightChild)
		rightChild->display(2 * i + 1);
}
//获取节点Element
template<typename T>
Element<T> BSTNode<T>::getElement()
{
	return data;
}


//树的成员函数

//构造初始化
	template<typename T>
	BST<T>::BST(BSTNode<T>*init = NULL)
	{
		root = init;
	}
//插入节点 
	template<typename T>
	bool BST<T>::BST_insert(const Element<T> &node)
	{
		BSTNode<T>*p = NULL;
		BSTNode<T>*q = root;
		while (q)//查找插入位置 最终肯定为叶子
		{
			p = q;
			if (node.key == q->data.key)
			{
				return false;
			}
			if (node.key > q->data.key)
			{
				q = q->rightChild;
			}
			else
			{
				q = q->leftChild;
			}
		}
        //创建新节点保存插入元素
		q = new BSTNode<T>;
		q->data = node;//Element数据类型浅拷贝,若Element包含指针元素得重载=操作符
		q->leftChild = NULL;
		q->rightChild = NULL;
        //空树的情况
		if (root == NULL)
		{
			root = q;
		}
		else
		{
			if (p->data.key > q->data.key)
			{
				p->leftChild = q;
			}
			else
			{
				p->rightChild = q;
			}
		}
		return true;
	}


//点展示树左右子树
//根据节点递归显示左右子树

	template<typename T>
	void BST<T>::display()
	{
		if (root == NULL)
		{
			cout << "树为空" << endl;
		}
		else
		{
			root->display(1);
		}
	}

	//查找节点 递归方法 
	//递归的部分需要传入根节点(BSTNode)
	//外部以Element类型加载数据,故写两个函数,改为一个Element端口
	template<typename T>
	BSTNode<T>*BST<T>::BST_Search(const Element<T>&node)
	{
		return BST_Search(root, node);
	}

	template<typename T>
	BSTNode<T>*BST<T>::BST_Search(BSTNode<T>*b, const Element<T>&node)
	{
		if (b == NULL)
		{
			return NULL;
		}
		if (node.key == b->data.key)
		{
			return b;
		}
		else if (node.key < b->data.key)
		{
			return BST_Search(b->leftChild, node);
		}
		else
		{
			return BST_Search(b->rightChild, node);
		}
	}
	
	//非递归查找 迭代方式实际中对大多数计算机更有效
	template<typename T>
	BSTNode<T>*BST<T>::BST_Search_Iterator(const Element<T>&node)
	{
		BSTNode<T>*t = root;
		while (t)
		{
			if (node.key == t->data.key)
			{
				return t;
			}
			else if (node.key < t->data.key)
			{
				t = t->leftChild;
			}
			else
			{
				t = t->rightChild;
			}
		}
	}

	//删除节点
	template<typename T>
	bool BST<T>::Delete_Node(const Element<T>&node)
	{
		if (root == NULL)
		{
			cout << "root == NULL" << endl;
			return 0;
		}
		BSTNode<T> *del = NULL;
		BSTNode<T> *pcurr = root;
		BSTNode<T> *parent = NULL;
		while (pcurr != NULL && pcurr->data.key != node.key)//先找到
		{
			if (node.key < pcurr->data.key)
			{
				parent = pcurr;
				pcurr = pcurr->leftChild;
			}
			if (node.key > pcurr->data.key)
			{
				parent = pcurr;
				pcurr = pcurr->rightChild;
			}
		}
		if (pcurr == NULL)//找了一遍没找到
		{
			return false;
		}
		if (pcurr->leftChild == NULL)//只有右孩子
		{
			if (pcurr == root)//如果是根节点 则根节点移动到右孩子即可
				root = root->rightChild;
			else if (pcurr == parent->leftChild)//若待删节点是parent左孩子
			{
				parent->leftChild = pcurr->rightChild;
			}
			else if (pcurr == parent->rightChild)//若待删除节点是parent右孩子
			{
				parent->rightChild = pcurr->rightChild;
			}
			del = pcurr;
		}
		else if (pcurr->rightChild == NULL)//只有左孩子
		{
			if (pcurr == root)
				root = root->leftChild;
			else if (pcurr == parent->leftChild)
			{
				parent->leftChild = pcurr->leftChild;
			}
			else
			{
				parent->rightChild = pcurr->leftChild;
			}
			del = pcurr;
		}
		else//既有左孩子又有右孩子 找到右子树最小(最左)的元素替换,在按照以上方式删除
		{
			//找到最左边的节点
			BSTNode<T> *left = pcurr->rightChild;
			parent = pcurr;
			while (left->leftChild)
			{
				parent = left;
				left = left->leftChild;
			}
			del = left;
			pcurr->data.key = left->data.key;//交换节点的值
			if (parent->leftChild == left)
			{
				parent->leftChild = left->rightChild;
			}
			else//当pcurr只有一个右节点时,left是parent的右子树
			{
				parent->rightChild = left->rightChild;
			}
		}
		delete del;
	}


	//中序遍历
	template<typename T>
	void BST<T>::midOrder()
	{
		midOrder(root);
	}
	template<typename T>
	void BST<T>::midOrder(BSTNode<T>*root)
	{
		if (root == NULL)
		{
			return;
		}
		midOrder(root->leftChild);
		cout<<root->getElement().key<<" "<<root->getElement().name<<"\t";
		midOrder(root->rightChild);
	}

	//返回树中最小的节点
	template<typename T>
	BSTNode<T>*	BST<T>::MinMum()
	{
		BSTNode<T>*tmp = root;
		while (tmp->leftChild)
		{
			tmp = tmp->leftChild;
		}
		return tmp;
	}

	//返回树种最大的节点
	template<typename T>
	BSTNode<T>*	BST<T>::MaxMum()
	{
		BSTNode<T>*tmp = root;
		while (tmp->rightChild)
		{
			tmp = tmp->rightChild;
		}
		return tmp;
	}

template<typename T>
	BST<T>::~BST()
	{
		delTree(root);
	}
	template<typename T>
	void BST<T>::delTree(BSTNode<T>*root)
	{
		BSTNode<T>*tmpLeft = NULL;
		BSTNode<T>*tmpRight = NULL;
		while (root)
		{
			tmpLeft = root->leftChild;
			tmpRight = root->rightChild;
			delete root;
			delTree(tmpLeft);
			delTree(tmpRight);
		}
	}

测试文件

#include"dm_04_BST.hpp"
#include"iostream"
#include"cmath"
using namespace std;

void main()
{
	Element<int> a,b,c,d,e,f,g,h;
	BST<int> tree;
	a.key = 5; a.name = 'a'; cout << tree.BST_insert(a) << endl;
	b.key = 2; b.name = 'b'; cout << tree.BST_insert(b) << endl;
	c.key = 7; c.name = 'c'; cout << tree.BST_insert(c) << endl;
	d.key = 1; d.name = 'd'; cout << tree.BST_insert(d) << endl;
	e.key = 6; e.name = 'e'; cout << tree.BST_insert(e) << endl;
	f.key = 8; f.name = 'f'; cout << tree.BST_insert(f) << endl;
	g.key = 4; g.name = 'g'; cout << tree.BST_insert(g) << endl;
	h.key = 0; h.name = 'h'; cout << tree.BST_insert(h) << endl;
	//打印二叉树,从根节点开始,递归打印左右	
	tree.display();

	cout << "递归搜索Key" << endl;
	cout<<tree.BST_Search(e)->getElement().key<<endl;

	cout << "迭代搜索Key" << endl;
	cout << tree.BST_Search_Iterator(e)->getElement().key<<endl;

	cout << "搜索二叉树中序遍历恰好是从小到大" << endl;
	tree.midOrder();

	cout << "二叉搜索树中键值最大的" << endl;
	Element<int> max = tree.MaxMum()->getElement();
	cout << "key: " << max.key << " name: " << max.name << endl;
	cout << "二叉搜索树中键值最小的" << endl;
	Element<int> min = tree.MinMum()->getElement();
	cout << "key: " << min.key << " name: " << min.name << endl;

	cout <<endl<< "删除节点d" << endl;
	tree.Delete_Node(d);
	tree.midOrder();
	cout << endl;
	system("pause");
}

 

测试运行结果

缺点:

二叉搜索树,在一定条件下会退化为链表,失去二叉搜索树的优点,构建二叉搜索树应当随机构建二叉搜索树,n个节点n!中排序,每一种排序等概。

平衡二叉树红黑树可以解决这个问题,有时间在努力封装一下红黑树吧。

有些颓废,希望自己能珍惜时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值