C++实现二叉排序树BSTree --插入删除摧毁查找等操作

一:二叉排序树定义

二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树。

二叉排序树是这样一棵树: (1)若左子树不空,则左子树上所有结点的值均小于它的
根结点的值; (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; (3)左、右子树也分别为二叉排序树;

(4)没有键值相等的结点。

二:删除算法(重点)

该树只有删除算法比较难,大概分为以下两种情况: (1)删除最多只有一棵子树的结点          此种情况,可用该节点的子树替代该节点的位置,如不存在子树,该节点为叶子结点,直接删除即可。 (2)删除存在两棵子树的节点          有两种解决方案,如下图:
《C++实现二叉排序树BSTree --插入删除摧毁查找等操作》 我们发现有两种解决方案:     I.用该节点的右子树的最左边一个叶子结点的值覆盖掉要删除的节点的值,由于该改动不会违背二叉排序树的根大于左,根小于右的性质,只需要将该叶子节点删除即可。     ii.用该节点的左子树的最右边一个叶子结点的值覆盖掉要删除的节点的值,同样删除该叶子节点即可。 不难发现,不论采用哪种方案,用来替换的节点正是要删除节点中序遍历的直接前驱或直接后继,这才导致了替换后整个二叉排序树依然是有序的,这种方案能够有效提高效率。

二:二叉排序树实现代码

#ifndef _BSTREE_H
#define _BSTREE_H

#include <iostream>
#include <assert.h>
using namespace std;

template <typename T>
class BSTree;

template <typename T>
class TreeNode{
	friend class BSTree<T>;
public:
	TreeNode() : m_data(T()), leftChild(NULL), rightChild(NULL)
	{}
	TreeNode(T data, TreeNode<T> *left = NULL, TreeNode<T> *right = NULL)
			: m_data(data), leftChild(left), rightChild(right)
	{}
	~TreeNode() = default;
private:
	T m_data;
	TreeNode<T> *leftChild;
	TreeNode<T> *rightChild;
};

template <typename T>
class BSTree{
	typedef TreeNode<T> node_type;
public:
	BSTree() :root(NULL)
	{}
	~BSTree();
public:
	BSTree<T>& operator=(const BSTree<T>&);

	void insert_elem(const T&);
	bool remove_elem(const T&);
	void inorder_traverse()const;

	T find_max()const;
	T find_min()const;
	node_type *search_elem(const T&)const;
protected:
	node_type *copy_tree(node_type *);

	void insert_elem(node_type *&, const T&);
	bool remove_elem(node_type *&, const T&);
	void inorder_traverse(node_type *)const;
	void destroy_tree(node_type *&);

	T find_max(node_type *)const;
	T find_min(node_type *)const;
	node_type *search_elem(node_type *, const T&)const;
private:
	node_type *root;
};

//public interface 

template <typename T>
BSTree<T>& BSTree<T>::operator=(const BSTree<T>& bst)
{
	if(this != &bst){
		root = copy_tree(bst.root);
	}
	return *this;
}

template <typename T>
BSTree<T>::~BSTree()
{
	destroy_tree(root);
}

template <typename T>
void BSTree<T>::insert_elem(const T& val)
{
	insert_elem(root, val);
}

template <typename T>
bool BSTree<T>::remove_elem(const T& val)
{
	remove_elem(root, val);
}

template <typename T>
void BSTree<T>::inorder_traverse()const
{
	inorder_traverse(root);
}

template <typename T>
T BSTree<T>::find_max()const
{
	return find_max(root);
}

template <typename T>
T BSTree<T>::find_min()const
{
	return find_min(root);
}

template <typename T>
TreeNode<T>* BSTree<T>::search_elem(const T& target)const
{
	search_elem(root, target);
}

//protected interface

template <typename T>
TreeNode<T>* BSTree<T>::copy_tree(node_type *t)
{
	node_type *tmp;
	if(t != NULL){
		tmp = new node_type(t->m_data);
		tmp->leftChild = copy_tree(t->leftChild);  //不能用tmp = copy_tree(t->leftChild)这样会导致新生成二叉树只挂有一个根节点
		tmp->rightChild = copy_tree(t->rightChild);
	}
	return tmp;
}

template <typename T>
void BSTree<T>::insert_elem(node_type *&t, const T& val)
{
	if(t == NULL){
		t = new node_type(val);
		return ;
	}
	
	if(t->m_data > val)
		insert_elem(t->leftChild, val);
	else if(t->m_data < val)
		insert_elem(t->rightChild, val);
	else 
		return ;
}

template <typename T>
void BSTree<T>::inorder_traverse(node_type *t)const
{	
	if(t != NULL){
		inorder_traverse(t->leftChild);
		cout << t->m_data << " ";
		inorder_traverse(t->rightChild);
	}
}

template <typename T>
bool BSTree<T>::remove_elem(node_type *&t, const T& val)
{
	if(t == NULL)
		return false;

	if(t->m_data > val)
		remove_elem(t->leftChild, val);
	else if(t->m_data < val)
		remove_elem(t->rightChild, val);
	else{
		if(t->leftChild != NULL && t->rightChild != NULL){
			node_type *tmp = t;
			tmp = t->rightChild;
			while(tmp->leftChild != NULL)
				tmp = tmp->leftChild; //选择右子树的最左边叶子结点替换方式
			t->m_data = tmp->m_data;
			remove_elem(t->rightChild, t->m_data);
			//delete tmp;           //error,此处不能直接delete,否则只能释放该节点,但该节点仍旧链接在二叉树上,需通过t指针释放并更改二叉树,另外一个原因是如果tmp元素有一个孩子,Remove递归会调用删除有一个孩子节点的情况,下面的else。例:上面图中38元素若存在一个右孩子39元素,就属于此类情况
		}
		else{
			node_type *tmp = t;
			if(t->leftChild != NULL)
				t = t->leftChild;
			else 
				t = t->rightChild;
			delete tmp;
		}
		return true;
	}
}

template <typename T>
void BSTree<T>::destroy_tree(node_type *&t)
{
	if(t != NULL){
		destroy_tree(t->rightChild);
		destroy_tree(t->leftChild);
		delete t;
	}
}

template <typename T>
T BSTree<T>::find_max(node_type *t)const
{
	while(t->leftChild != NULL)
		t = t->leftChild;
	return t->m_data;
}

template <typename T>
T BSTree<T>::find_min(node_type *t)const
{
	while(t->rightChild != NULL)
		t = t->rightChild;
	return t->m_data;
}

template <typename T>
TreeNode<T>* BSTree<T>::search_elem(node_type *t, const T& target)const
{
	if(t == NULL)
		return NULL;	
	else if(t->m_data > target)
		search_elem(t->leftChild, target);
	else if(t->m_data < target)
		search_elem(t->rightChild, target);
	else
		return t;
}

#endif /*BSTree.h*/

三:测试代码

测试代码如下:

#include "BSTree.h"

int main()
{
	int array[] = {32, 43, 1, 76, 54, 13, 42, 18, 139, 4};
	BSTree<int> bst;

	int len = sizeof(array) / sizeof (int);
	for(int i=0; i<len; ++i){
		bst.insert_elem(array[i]);
	}

	bst.inorder_traverse();
	cout << endl;	

	cout << bst.find_max() << endl;
	cout << bst.find_min() << endl;
	
	cout << bst.search_elem(139) << endl;

	bst.remove_elem(32);
	bst.inorder_traverse();
	cout << endl;

	BSTree<int> bst_;
	bst_ = bst;
	bst_.inorder_traverse();
	cout << endl;

	return 0;
}

测试结果如图:
《C++实现二叉排序树BSTree --插入删除摧毁查找等操作》

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/FreeeLinux/article/details/52185123
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞