二叉查找树解析及其C++实现

介绍

二叉查找树,又称二叉搜索树、有序二叉树、排序二叉树。

它是特殊的二叉树,对于二叉树,假设x为二叉树中的任意一个结点,x结点包含关键字key,结点x的key值记为key[ x ]。如果y是x的左子树中的一个结点,则key[ y ] <= key[ x ];如果y是x的右子树中的一个结点,则key[ y ] >= key[ x ];那么,这棵树就是二叉查找树,如下图所示:



二叉查找树具有以下性质:
1)若任意结点的左子树非空,则左子树上所有结点的值均小于它的根节点的值

2)若任意结点的右子树非空,则右子树上所有结点的值均大于它的根节点的值

3)任意结点的左、右子树叶分别为二叉查找树

4)没有键值相等的结点



————————————————————————————————————————————————————————————————————————————

算法实现

结点和二叉查找树的定义

template<class T>
class BSTNode
{
	public:
		T key;	// 关键字(键值)
		BSTNode *left;	// 左孩子
		BSTNode *right;	// 右孩子
		BSTNode *parent;	// 父结点
		
		BSTNode(T value, BSTNode *p, BSTNode *l, BSTNode *r):
			key(value),parent(p),left(l),right(r) {} 
};

template<class T>
class BSTree
{
	private:
		BSTNode<T> *root;	// 根结点 
	
	public:
		BSTree();
		~BSTree();
		
		// 前序遍历
		void preOrder();
		// 中序遍历
		void inOrder();
		// 后序遍历
		void postOrder();
		
		// (递归实现)查找二叉树中键值为key的结点
		BSTNode<T>* search(T key);
		// (非递归实现) 查找二叉树中键值为key的结点
		BSTNode<T>* iterativeSearch(T key);
		
		// 查找最小结点(返回键值)
		T minimum(); 
		// 查找最大结点(返回键值)
		T maximum();
		
		// 找结点(x)的后继结点。即查找二叉树中键值大于该结点的最小结点
		BSTNode<T>* successor(BSTNode<T> *x);
		// 找结点(x)的前驱结点。即查找二叉树中键值小于该结点的最大结点
		BSTNode<T>* predecessor(BSTNode<T> *x);
		
		// 将键值为key的结点插入到二叉树中
		void insert(T key);
		
		// 删除键值为key的结点
		void remove(T key);
		
		// 销毁二叉树
		void destroy();
		
		// 打印二叉树
		void print();
		
	private:
		// 重载函数,提供内部接口
		// 前序遍历
		void preOrder(BSTNode<T> *tree) const;
		// 中序遍历
		void inOrder(BSTNode<T> *tree) const;
		// 后序遍历
		void postOrder(BSTNode<T> *tree) const;
		
		// (递归实现)查找二叉树中键值为key的结点
		BSTNode<T>* search(BSTNode<T> *x, T key) const;
		// (非递归实现) 查找二叉树中键值为key的结点
		BSTNode<T>* iterativeSearch(BSTNode<T> *x, T key) const;
		
		// 查找最小结点(返回键值)
		BSTNode<T>* minimum(BSTNode<T> *tree); 
		// 查找最大结点(返回键值)
		BSTNode<T>* maximum(BSTNode<T> *tree);
		
		// 将结点z插入到二叉树tree中 
		void insert(BSTNode<T>* &tree, BSTNode<T> *z);
		
		// 删除二叉树中的结点z,并返回该结点 
		BSTNode<T>* remove(BSTNode<T>* &tree, BSTNode<T> *z);
		
		// 销毁二叉树
		void destroy(BSTNode<T>* &tree);
		
		// 打印二叉树
		void print(BSTNode<T>* &tree, T key, int direction);
};


遍历

前序遍历

template<class T>
void BSTree<T>::preOrder(BSTNode<T> *tree) const
{
	if(tree!=NULL)
	{
		cout<<tree->key<<" ";
		preOrder(tree->left);
		preOrder(tree->right);
	} 
}

template<class T>
void BSTree<T>::preOrder()
{
	preOrder(root);
}

中序遍历

template<class T>
void BSTree<T>::inOrder(BSTNode<T> *tree) const
{
	if(tree!=NULL)
	{
		inOrder(tree->left);
		cout<<tree->key<<" ";
		inOrder(tree->right);
	} 
}

template<class T>
void BSTree<T>::inOrder()
{
	inOrder(root);
}

后序遍历

template<class T>
void BSTree<T>::postOrder(BSTNode<T> *tree) const
{
	if(tree!=NULL)
	{
		postOrder(tree->left);
		postOrder(tree->right);
		cout<<tree->key<<" ";
	} 
}

template<class T>
void BSTree<T>::postOrder()
{
	postOrder(root);
}

查找

递归方式进行查找

template<class T>
BSTNode<T>* BSTree<T>::search(BSTNode<T>* x, T key) const
{
	if(x==NULL || x->key==key)
		return x;
	if(key<x->key)
		search(x->left, key);
	else
		search(x->right, key);
}

template<class T>
BSTNode<T>* BSTree<T>::search(T key)
{
	search(root, key);
}

非递归方式进行查找

template<class T>
BSTNode<T>* BSTree<T>::interativeSearch(BSTNode<T>* x, T key) const
{
	while(x!=NULL && x->key!=key)
	{
		if(key<x->key)
			x = x->left;
		else
			x = x->right;
	}
	return x;
}

template<class T>
BSTNode<T>* BSTree<T>::interativeSearch(T key)
{
	interativeSearch(root, key);
}


最大值和最小值

查找最大值

template<class T>
BSTNode<T>*  BSTree<T>::maximum(BSTNode<T> *tree)
{
	if(tree==NULL)
		return NULL;
	while(tree->right!=NULL)
		tree = tree->right;
	return tree;
}

template<class T>
T BSTree<T>::maximum()
{
	BSTNode<T> *p = maximum(root);
	if(p!=NULL)
		return p->key;
	return (T)NULL;
}


查找最小值

template<class T>
BSTNode<T>*  BSTree<T>::minimum(BSTNode<T> *tree)
{
	if(tree==NULL)
		return NULL;
	while(tree->left!=NULL)
		tree = tree->left;
	return tree;
}

template<class T>
T BSTree<T>::minimum()
{
	BSTNode<T> *p = minimum(root);
	if(p!=NULL)
		return p->key;
	return (T)NULL;
}


前驱和后继

查找前驱

template<class T>
BSTNode<T>* BSTree<T>::predecessor(BSTNode<T> *x)
{
	// 如果x存在左孩子,则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。
	if(x->left!=NULL)
		return maximum(x->left);
	// 如果x没有左孩子。则x有以下两种可能:
    // (1) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。
    // (2) x是"一个左孩子",则查找"x的最低的父结点,并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"。
    BSTNode<T> *p = x->parent;
    while(p!=NULL && x==p->left)
    {
    	x = p;
    	p = p->parent;
	}
	return p;
}

查找后继

template<class T>
BSTNode<T>* BSTree<T>::successor(BSTNode<T> *x)
{
	// 如果x存在右孩子,则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。
	if(x->right!=NULL)
		return minimum(x->right);
	// 如果x没有右孩子。则x有以下两种可能:
    // (1) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。
    // (2) x是"一个右孩子",则查找"x的最低的父结点,并且该父结点要具有左孩子",找到的这个"最低的父结点"就是"x的后继结点"。
    BSTNode<T> *p = x->parent;
    while(p!=NULL && x==p->right)
    {
    	x = p;
    	p = p->parent;
	}
	return p;
}


插入

template<class T>
void BSTree<T>::insert(BSTNode<T>* &tree, BSTNode<T> *z)
{
	BSTNode<T> *y = NULL;
	BSTNode<T> *x = tree;
	
	// 查找z的插入位置
	while(x!=NULL)
	{
		y = x;
		if(z->key < x->key)
			x = x->left;
		else	// else if(z->key > x->key)
			x = x->right;
//		若禁止插入相同键值
//		else
//		{
//			free(z);// 释放之前分配的结点 
//			return;
//		}
	}
	z->parent = y;
	if(y==NULL)
		tree = z;
	else if(z->key<y->key)
		y->left = z;
	else
		y->right = z;
}

template<class T>
void BSTree<T>::insert(T key)
{
	BSTNode<T> *z = NULL;
	
	// 如果新建结点失败,则返回
	if((z=new BSTNode<T>(key,NULL,NULL,NULL))==NULL)
		return;
		
	insert(root,z); 
}


删除

template<class T>
BSTNode<T>* BSTree<T>::remove(BSTNode<T>* &tree, BSTNode<T> *z)
{
	BSTNode<T> *x = NULL;
	BSTNode<T> *y = NULL;
	
	if(z->left==NULL || z->right==NULL)
		y = z;
	else
		y = successor(z);
	
	if(y->left!=NULL)
		x = y->left;
	else
		x = y->right;
	
	if(x!=NULL)
		x->parent = y->parent;
		
	if(y->parent==NULL)
		tree = x;
	else if(y==y->parent->left)
		y->parent->left = x;
	else
		y->parent->right = x;
		
	if(y!=z)
		z->key = y->key;
	return y;
}

template<class T>
void BSTree<T>::remove(T key)
{
	BSTNode<T> *z, *node;
	
	if((z=search(root,key))!=NULL)
		if((node=remove(root,z))!=NULL)
			delete node;
}


打印

template<class T>
void BSTree<T>::print(BSTNode<T> *tree, T key, int direction)
{
	if(tree!=NULL)
	{
		if(direction==0)
			cout<<setw(2)<<tree->key<<"is root"<<endl;
		else
			cout<<setw(2)<<tree->key<<"is"<<setw(2)<<key<<"'s"<<setw(12)<<(direction==1 ? "right child":"left child")<<endl;
		print(tree->left,tree->key,-1);
		print(tree->right,tree->key,1);
	}
}

template<class T>
void BSTree<T>::print()
{
	if(root!=NULL)
		print(root,root->key,0);
}


销毁

template<class T>
void BSTree<T>::destroy(BSTNode<T> *&tree)
{
	if(tree==NULL)
		return ;
	if(tree->left!=NULL)
		return destroy(tree->left);
	if(tree->right!=NULL)
		return destroy(tree->right);
	
	delete tree;
	tree=NULL;
}

template<class T>
void BSTree<T>::destroy()
{
	destroy(root);
}


————————————————————————————————————————————————————————————————————————————

二叉查找树完整实现:BSTree.h

#ifndef BINARY_SEARCH_TREE
#define BINARY_SEARCH_TREE

#include<iomanip>
#include<iostream>
using namespace std;

template<class T>
class BSTNode
{
	public:
		T key;	// 关键字(键值)
		BSTNode *left;	// 左孩子
		BSTNode *right;	// 右孩子
		BSTNode *parent;	// 父结点
		
		BSTNode(T value, BSTNode *p, BSTNode *l, BSTNode *r):
			key(value),parent(p),left(l),right(r) {} 
};

template<class T>
class BSTree
{
	private:
		BSTNode<T> *root;	// 根结点 
	
	public:
		BSTree() {};
		~BSTree() {};
		
		// 前序遍历
		void preOrder();
		// 中序遍历
		void inOrder();
		// 后序遍历
		void postOrder();
		
		// (递归实现)查找二叉树中键值为key的结点
		BSTNode<T>* search(T key);
		// (非递归实现) 查找二叉树中键值为key的结点
		BSTNode<T>* iterativeSearch(T key);
		
		// 查找最小结点(返回键值)
		T minimum(); 
		// 查找最大结点(返回键值)
		T maximum();
		
		// 找结点(x)的后继结点。即查找二叉树中键值大于该结点的最小结点
		BSTNode<T>* successor(BSTNode<T> *x);
		// 找结点(x)的前驱结点。即查找二叉树中键值小于该结点的最大结点
		BSTNode<T>* predecessor(BSTNode<T> *x);
		
		// 将键值为key的结点插入到二叉树中
		void insert(T key);
		
		// 删除键值为key的结点
		void remove(T key);
		
		// 销毁二叉树
		void destroy();
		
		// 打印二叉树
		void print();
		
	private:
		// 重载函数,提供内部接口
		// 前序遍历
		void preOrder(BSTNode<T> *tree) const;
		// 中序遍历
		void inOrder(BSTNode<T> *tree) const;
		// 后序遍历
		void postOrder(BSTNode<T> *tree) const;
		
		// (递归实现)查找二叉树中键值为key的结点
		BSTNode<T>* search(BSTNode<T> *x, T key) const;
		// (非递归实现) 查找二叉树中键值为key的结点
		BSTNode<T>* iterativeSearch(BSTNode<T> *x, T key) const;
		
		// 查找最小结点(返回键值)
		BSTNode<T>* minimum(BSTNode<T> *tree); 
		// 查找最大结点(返回键值)
		BSTNode<T>* maximum(BSTNode<T> *tree);
		
		// 将结点z插入到二叉树tree中 
		void insert(BSTNode<T>* &tree, BSTNode<T> *z);
		
		// 删除二叉树中的结点z,并返回该结点 
		BSTNode<T>* remove(BSTNode<T>* &tree, BSTNode<T> *z);
		
		// 销毁二叉树
		void destroy(BSTNode<T>* &tree);
		
		// 打印二叉树
		void print(BSTNode<T>* &tree, T key, int direction);
};

template<class T>
BSTree<T>::BSTree(): root(NULL)
{ 
}

template<class T>
BSTree<T>::~BSTree()
{
    destroy(root);
}

template<class T>
void BSTree<T>::preOrder(BSTNode<T> *tree) const
{
	if(tree!=NULL)
	{
		cout<<tree->key<<" ";
		preOrder(tree->left);
		preOrder(tree->right);
	} 
}

template<class T>
void BSTree<T>::preOrder()
{
	preOrder(root);
}

template<class T>
void BSTree<T>::inOrder(BSTNode<T> *tree) const
{
	if(tree!=NULL)
	{
		inOrder(tree->left);
		cout<<tree->key<<" ";
		inOrder(tree->right);
	} 
}

template<class T>
void BSTree<T>::inOrder()
{
	inOrder(root);
}

template<class T>
void BSTree<T>::postOrder(BSTNode<T> *tree) const
{
	if(tree!=NULL)
	{
		postOrder(tree->left);
		postOrder(tree->right);
		cout<<tree->key<<" ";
	} 
}

template<class T>
void BSTree<T>::postOrder()
{
	postOrder(root);
}

template<class T>
BSTNode<T>* BSTree<T>::search(BSTNode<T>* x, T key) const
{
	if(x==NULL || x->key==key)
		return x;
	if(key<x->key)
		return search(x->left, key);
	else
		return search(x->right, key);
}

template<class T>
BSTNode<T>* BSTree<T>::search(T key)
{
	search(root, key);
}

template<class T>
BSTNode<T>* BSTree<T>::iterativeSearch(BSTNode<T>* x, T key) const
{
	while(x!=NULL && x->key!=key)
	{
		if(key<x->key)
			x = x->left;
		else
			x = x->right;
	}
	return x;
}

template<class T>
BSTNode<T>* BSTree<T>::iterativeSearch(T key)
{
	iterativeSearch(root, key);
}

template<class T>
BSTNode<T>*  BSTree<T>::maximum(BSTNode<T> *tree)
{
	if(tree==NULL)
		return NULL;
	while(tree->right!=NULL)
		tree = tree->right;
	return tree;
}

template<class T>
T BSTree<T>::maximum()
{
	BSTNode<T> *p = maximum(root);
	if(p!=NULL)
		return p->key;
	return (T)NULL;
}

template<class T>
BSTNode<T>*  BSTree<T>::minimum(BSTNode<T> *tree)
{
	if(tree==NULL)
		return NULL;
	while(tree->left!=NULL)
		tree = tree->left;
	return tree;
}

template<class T>
T BSTree<T>::minimum()
{
	BSTNode<T> *p = minimum(root);
	if(p!=NULL)
		return p->key;
	return (T)NULL;
}

template<class T>
BSTNode<T>* BSTree<T>::predecessor(BSTNode<T> *x)
{
	// 如果x存在左孩子,则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。
	if(x->left!=NULL)
		return maximum(x->left);
	// 如果x没有左孩子。则x有以下两种可能:
    // (1) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。
    // (2) x是"一个左孩子",则查找"x的最低的父结点,并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"。
    BSTNode<T> *p = x->parent;
    while(p!=NULL && x==p->left)
    {
    	x = p;
    	p = p->parent;
	}
	return p;
}

template<class T>
BSTNode<T>* BSTree<T>::successor(BSTNode<T> *x)
{
	// 如果x存在右孩子,则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。
	if(x->right!=NULL)
		return minimum(x->right);
	// 如果x没有右孩子。则x有以下两种可能:
    // (1) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。
    // (2) x是"一个右孩子",则查找"x的最低的父结点,并且该父结点要具有左孩子",找到的这个"最低的父结点"就是"x的后继结点"。
    BSTNode<T> *p = x->parent;
    while(p!=NULL && x==p->right)
    {
    	x = p;
    	p = p->parent;
	}
	return p;
}

template<class T>
void BSTree<T>::insert(BSTNode<T>* &tree, BSTNode<T> *z)
{
	BSTNode<T> *y = NULL;
	BSTNode<T> *x = tree;
	
	// 查找z的插入位置
	while(x!=NULL)
	{
		y = x;
		if(z->key < x->key)
			x = x->left;
		else	// else if(z->key > x->key)
			x = x->right;
//		若禁止插入相同键值
//		else
//		{
//			free(z);// 释放之前分配的结点 
//			return;
//		}
	}
	z->parent = y;
	if(y==NULL)
		tree = z;
	else if(z->key<y->key)
		y->left = z;
	else
		y->right = z;
}

template<class T>
void BSTree<T>::insert(T key)
{
	BSTNode<T> *z = NULL;
	
	// 如果新建结点失败,则返回
	if((z=new BSTNode<T>(key,NULL,NULL,NULL))==NULL)
		return;
		
	insert(root,z); 
}

template<class T>
BSTNode<T>* BSTree<T>::remove(BSTNode<T>* &tree, BSTNode<T> *z)
{
	BSTNode<T> *x = NULL;
	BSTNode<T> *y = NULL;
	
	if(z->left==NULL || z->right==NULL)
		y = z;
	else
		y = successor(z);
	
	if(y->left!=NULL)
		x = y->left;
	else
		x = y->right;
	
	if(x!=NULL)
		x->parent = y->parent;
		
	if(y->parent==NULL)
		tree = x;
	else if(y==y->parent->left)
		y->parent->left = x;
	else
		y->parent->right = x;
		
	if(y!=z)
		z->key = y->key;
	return y;
}

template<class T>
void BSTree<T>::remove(T key)
{
	BSTNode<T> *z, *node;
	
	if((z=search(root,key))!=NULL)
		if((node=remove(root,z))!=NULL)
			delete node;
}

template<class T>
void BSTree<T>::print(BSTNode<T> *&tree, T key, int direction)
{
	if(tree!=NULL)
	{
		if(direction==0)
			cout<<setw(2)<<tree->key<<"is root"<<endl;
		else
			cout<<setw(2)<<tree->key<<"is"<<setw(2)<<key<<"'s"<<setw(12)<<(direction==1 ? "right child":"left child")<<endl;
		print(tree->left,tree->key,-1);
		print(tree->right,tree->key,1);
	}
}

template<class T>
void BSTree<T>::print()
{
	if(root!=NULL)
		print(root,root->key,0);
}

template<class T>
void BSTree<T>::destroy(BSTNode<T> *&tree)
{
	if(tree==NULL)
		return ;
	if(tree->left!=NULL)
		return destroy(tree->left);
	if(tree->right!=NULL)
		return destroy(tree->right);
	
	delete tree;
	tree=NULL;
}

template<class T>
void BSTree<T>::destroy()
{
	destroy(root);
}

#endif


测试代码:BSTreeTest.cpp

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

static int arr[] = {1,5,4,3,2,6};

int main()
{
	int i,len;
	BSTree<int> *tree = new BSTree<int>();
	
	cout<<"依次添加:";
	len = sizeof(arr)/sizeof(arr[0]);
	for(i=0;i<len;++i)
	{
		cout<<arr[i]<<" ";
		tree->insert(arr[i]);
	}
	
	cout<<"\n前序遍历:";
	tree->preOrder();
	cout<<"\n中序遍历:";
	tree->inOrder();
	cout<<"\n后序遍历:";
	tree->postOrder();
	cout<<endl;
	
	cout<<"最小值:"<<tree->minimum()<<endl;
	cout<<"最大值:"<<tree->maximum()<<endl;
	cout<<"树的详细信息:"<<endl;
	tree->print();
	
	cout<<" \n删除根节点:"<<arr[3];
	tree->remove(arr[3]);
	
	cout<<"\n中序遍历:";
	tree->inOrder();
	cout<<endl;
	
	// 销毁二叉树
	tree->destroy();

	return 0; 
}


参考资料:

感谢作者如果天空不死 戳我进原博

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值