数据结构与算法-二叉查找树

二叉树基本概念

二叉查找树的实现,包括查找元素、查找最大最小值、插入元素、删除元素、清空二叉树等操作。
二叉查找树的平均深度是O(log N),因此查找的平均时间复杂度也是O(log N),但是当二叉查找树不平衡时比如退化成单链表时,查找元素所需的平均时间复杂度为O(N),二叉平衡树可以解决不平衡的问题。

部分代码实现

template <typename Comparable>
class BinarySearchTree{

public:
	BinarySearchTree();
	BinarySearchTree(const BinarySearchTree & T);
	BinarySearchTree(BinarySearchTree && T);
	BinarySearchTree & operator=(const BinarySearchTree & T);
	BinarySearchTree & operator=(BinarySearchTree && T);
	~BinarySearchTree();

	const Comparable & findMax() const;
	const Comparable & findMin() const;
	bool contains(const Comparable & x) const;
	void insert(const Comparable & x);
	void insert(Comparable && x);
	void remove(const Comparable & x);
	void makeEmpty();


private:
	struct BinaryNode{
		Comparable element;
		BinaryNode* left;
		BinaryNode* right;

		BinaryNode(const Comparable & x,BinaryNode* lt,BinaryNode* rt):
			element{x},left{lt},right{rt} {}

		BinaryNode(Comparable && x,BinaryNode* lt,BinaryNode* rt):
			element{std::move(x)},left{lt},right{rt} {}
	};

	BinaryNode* root;

	void insert(const Comparable & x,BinaryNode* t);
	void insert(Comparable && x,BinaryNode* t);
	void remove(const Comparable & x,BinaryNode* t);
	BinaryNode* findMax(BinaryNode* t) const;
	BinaryNode* findMin(BinaryNode* t) const;
	bool contains(const Comparable & x,BinaryNode* t) const;
	void makeEmpty(BinaryNode* & t);
	BinaryNode* clone(BinaryNode* t) const;
}; 

//查找
template <typename Comparable>
bool BinarySearchTree<Comparable>::contains(const Comparable & x) const
{
	return contains(x,root);
}

template <typename Comparable>
bool BinarySearchTree<Comparable>::contains(const Comparable & x,BinaryNode* t) const
{
	if(t==nullptr)
		return false;
	
	if(x > t->element)
		return contains(x,t->right);
	else if(x < t->element)
		return contains(x,t->left);
	else
		return true;
}

//查找最大值
template <typename Comparable>
const Comparable & BinarySearchTree<Comparable>::findMax() const
{
	return findMax(root)->element;
}

template <typename Comparable>
typename BinarySearchTree<Comparable>::BinaryNode* BinarySearchTree<Comparable>::findMax(BinaryNode* t) const
{
	if(t==nullptr)
		return nullptr;
	if(t->left == nullptr)
		return t;
	
	return findMax(t->left);
}

//查找最小值
template <typename Comparable>
const Comparable & BinarySearchTree<Comparable>::findMin() const
{
	return findMin(root)->element;
}

template <typename Comparable>
typename BinarySearchTree<Comparable>::BinaryNode* 
	BinarySearchTree<Comparable>::findMin(BinaryNode* t) const
{
	if(t==nullptr)
		return nullptr;

	while(t->right != nullptr)
		t=t->right;

	return t;
}

//插入
template <typename Comparable>
void BinarySearchTree<Comparable>::insert(const Comparable & x)
{
	insert(x,root);
}

template <typename Comparable>
void BinarySearchTree<Comparable>::insert(const Comparable & x,BinaryNode* t)
{
	if(t==nullptr)
	{
		t = new BinaryNode(x,nullptr,nullptr);
	}

	if(x > t->element)
		insert(x,t->right);
	else if(x < t->element)
		insert(x,t->left);
}

template <typename Comparable>
void BinarySearchTree<Comparable>::insert(Comparable && x)
{
	insert(std::move(x),root);
}

template <typename Comparable>
void BinarySearchTree<Comparable>::insert(Comparable && x,BinaryNode* t)
{
	if(t==nullptr)
	{
		t = new BinaryNode(std::move(x),nullptr,nullptr);
	}

	if(x > t->element)
		insert(std::move(x),t->right);
	else if(x < t->element)
		insert(std::move(x),t->left);
}

//删除
template <typename Comparable>
void BinarySearchTree<Comparable>::remove(const Comparable & x)
{
	remove(x,root);
}

template <typename Comparable>
void BinarySearchTree<Comparable>::remove(const Comparable & x,BinaryNode* t)
{
	if(t==nullptr)
		return;

	if(x > t->element)
		remove(x,t->right);
	else if(x < t->element)
		remove(x,t->left);
	else if(t->left != nullptr && t->right != nullptr)
	{
		t->element = findMin(t->right)->element;
		remove(t->element,t->right);
	}
	else
	{
		BinaryNode* old = t;
		t = (t->right==nullptr)?t->left:t->right;
		delete old;
	}
}

//清空
template <typename Comparable>
void BinarySearchTree<Comparable>::makeEmpty()
{
	makeEmpty(root);
}

template <typename Comparable>
void BinarySearchTree<Comparable>::makeEmpty(BinaryNode* & t)
{
	if(t!=nullptr)
	{
		makeEmpty(t->left);
		makeEmpty(t->right);
		delete t;
	}

	t = nullptr;
}

//析构函数
template <typename Comparable>
BinarySearchTree<Comparable>::~BinarySearchTree()
{
	makeEmpty();
}

//克隆
template <typename Comparable>
typename BinarySearchTree<Comparable>::BinaryNode* BinarySearchTree<Comparable>::clone(BinaryNode* t) const
{
	if(t==nullptr)
		return nullptr;

	return new BinaryNode{t->element,clone(t->left),clone(t->right)};
}

//复制构造函数
template <typename Comparable>
BinarySearchTree<Comparable>::BinarySearchTree(const BinarySearchTree & T)
{
	root = clone(T.root);
}

c+语法注意点:

1.类外定义成员函数问题:需要在函数前加类作用域;类外使用的子类除了要加作用域外还要在其前面加typename关键字,否则有的编译器会识别不出是该名字是子类名还是变量名。
2.模板类外定义成员函数时要在函数前加template声明。
3.类外定义的成员函数内部使用类成员(包括成员变量,成员函数以及内部子类)时不用加类作用域。
4. std::move(x) 把x变成右值,不论x之前是右值还是左值。

参考文献:

维斯 –《数据结构与算法分析:C++语言描述》第四版

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