二叉树基本概念
二叉查找树的实现,包括查找元素、查找最大最小值、插入元素、删除元素、清空二叉树等操作。
二叉查找树的平均深度是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++语言描述》第四版