二叉查找树的实现

二叉查找树是这样定义的:

二叉查找树(Binary Search Tree),或者是一棵空树,或者是具有下列性质的二叉树:

  1. 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  2. 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  3. 它的左、右子树也分别为二叉排序树

二叉查找树是一种高效的搜寻树,类似于如下:


以下是我参考网上的资源实现的:
#include <iostream>
using namespace std;

/*二叉查找树的节点类*/
template <class T> 
class TreeNode
{
public:
	TreeNode():left(NULL),right(NULL),freq(1){}
	T data;
	unsigned int freq;
	TreeNode *left;
	TreeNode *right;
};

/*二叉查找树类*/
template <class T> 
class BST
{
public:
	BST():root(NULL){}
	void insert(T x);//提供的公共接口
	void traversal();
	TreeNode<T> *find(T x);
	void Delete(T x);
private:
	TreeNode<T> *root;
	void insert_node(TreeNode<T>* &node, T x);
	void InOrder(TreeNode<T> *node);
	TreeNode<T> *findnode(TreeNode<T> *node, T x);
	void delete_node(TreeNode<T> *&node, T x);
};

template<class T> 
void BST<T>::insert_node(TreeNode<T>* &node, T x)
{
	if(node == NULL)
	{
		node  = new TreeNode<T>();
		node->data = x;
		return;
	}
	if(node->data > x)
		insert_node(node->left, x);
	else if(node->data < x)
		insert_node(node->right, x);
	else
		(node->freq)++;//频数加1
} 


template<class T> 
void BST<T>::insert(T x)
{
	insert_node(root, x);
}

template<class T>
void BST<T>::traversal()
{
	InOrder(root);
}

template <class T>
void BST<T>::InOrder(TreeNode<T> *node)
{
	if(node != NULL)
	{
		InOrder(node->left);
		cout<<node->data<<endl;
		InOrder(node->right);
	}
}

template <class T>
TreeNode<T>* BST<T>::find(T x)
{
	return findnode(root, x);
}
template <class T>
TreeNode<T>* BST<T>::findnode(TreeNode<T>* node, T x)
{
	if(node == NULL)  return NULL;//类似于二分法查找

	if(node->data == x)
		return node;
	else if(node->data < x)
		return findnode(node->right, x);
	else
		return findnode(node->left, x);
}

template<class T>
void BST<T>::Delete(T x)
{
	delete_node(root, x);
}

template<class T>
void BST<T>::delete_node(TreeNode<T> *&node, T x)
{
	if(node == NULL) return;
	if(node->data > x)
		delete_node(node->left, x);
	else if(node->data < x)
		delete_node(node->right, x);

	else
	{
		if(node->left != NULL && node->right != NULL)//有两个孩子节点
		{
			TreeNode<T>*temp = node->right;
			while(temp->left != NULL) temp = temp->left;//找到右子树中最小的孩子节点
			node->data = temp->data;
			node->freq = temp->freq;
			delete_node(node->right, node->data);//删除右子树中最小的孩子节点
		}
		else//有1个或者0个孩子节点
		{
			TreeNode<T>* temp = node;
			if(node->left == NULL)
				node = node->right;
			else if(node->right == NULL)
				node= node->left;
		}
	}
}

int main()
{
	int a[] = {3,2,5,6,4,1};
	BST<int> *bst = new BST<int>();
	
	for(int i = 0; i < sizeof(a)/sizeof(a[0]); i++)
		bst->insert(a[i]);
	bst->traversal();

	TreeNode<int> *node = bst->find(a[3]);
	if(node != NULL)
		cout<<"find the data "<<node->data<<endl;
	else
		cout<<"can't find the data"<<endl;

	bst->Delete(a[0]);
	cout<<"after delete "<<a[0]<<endl;
	bst->traversal();

	return 0;
}

下面对算法进行解释:
定义BST的时候我们使用了一个私有的接口和一个公有的接口,是一个小技巧,体现了C++的封装性

insert函数:
想要构造一个二叉查找树,每一次都是把一个节点插入到现有的二叉查找树中,在插入的过程中,递归比较,如果比该节点大就往右插入,否则往左插入

traversal()函数:
中序遍历二叉树能够得到一个有序的数列,因为我们二叉查找树就是定义成node->left->data i小于node->data小于node->right->data,如果按照中序遍历自然是有序的了

delete()函数:
删除一个节点比较复杂,因为要考虑到这个节点是否有孩子,以及孩子的个数,可以分类来考虑,其实不难:
1.如果没有孩子节点,直接删除这节点就是了
2.如果有一个孩子节点,就用这个孩子节点来代替这个节点
3.如果有两个孩子节点,约定俗成的用右子树中最小的节点来代替这个节点,其实就是右子树的最最左子节点y


二叉查找树有其弊端,我们说其查找,插入的时间复杂度是 O(logn)但是但我们的测试数组是{1,2,3,4,5,6}的时候,构造的二叉查找树就是这样的了
1
  2  
   3
     4
       5
         6
那么我们的搜寻时间就变为了O(n)线性的了这个就不能体现它的优势了,所以我们可以优化,优化的方法可以有红黑树和AVL树等


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值