查找二叉树的实现,参考第四版教材P109页。
需要注意的是,对于含n个结点的二叉树,树的平均高度为h=「log(n+1)|。 但是如果给定的是有序的递增递减的数,那么树的高度就为n, 即只存在左子树或右子树,所以为了降低树的高度,减小搜索复杂度,最好给定无序的数值。
binarySearchTree.h 文件:
#pragma once
#include <ostream>
template <typename Comparable>
class BinarySearchTree
{
public:
BinarySearchTree():root(nullptr){};
BinarySearchTree(const BinarySearchTree & rhs) : root(nullptr)
{
root = clone(rhs.root);
}
BinarySearchTree(BinarySearchTree && rhs) : root(nullptr)
{
root = clone(std::move(rhs.root))
}
~BinarySearchTree() { makeEmpty(); }
const Comparable & findMin() const { return findMin(root)->element; }
const Comparable & findMax() const { return findMax(root)->element; }
bool contains(const Comparable & x)const { return contains(x, root); } /* 如果在树中找到x, 返回true.*/
bool isEmpty() const { return root == nullptr; };
void printTree(std::ostream & out = cout)const
{
if (isEmpty())
out << "Empty tree" << endl;
else
printTree(root, out);
}
void makeEmpty() { makeEmpty(root); }
void insert(const Comparable & x) { insert(x, root); } /*将x插入树中,忽略重复元*/
void insert(Comparable ** x) { insert(std::move(x), root); }
void remove(const Comparable & x) { remove(x, root); };
BinarySearchTree & operator = (const BinarySearchTree & rhs)
{
if (this != &rhs)
{
BinaryNode *tmp = clone(rhs.root);
makeEmpty();
root = tmp;
}
return *this;
}
BinarySearchTree & operator =(BinarySearchTree && rhs)
{
if (this != std::move(rhs))
{
BinaryNode *tmp = clone(std::move(rhs.root));
makeEmpty();
root = tmp;
}
return *this;
}
private:
struct BinaryNode {
Comparable element;
BinaryNode *left;
BinaryNode *right;
BinaryNode(const Comparable & theElement, BinaryNode *lt, BinaryNode *rt)
: element(theElement),left(lt),right(rt) { }
BinaryNode (Comparable && theElement, BinaryNode *lt ,BinaryNode *rt)
: element(std::move(theElement)),left(lt),right(rt) { }
};
BinaryNode *root;
void insert(const Comparable & x, BinaryNode * & t);
void insert(const Comparable &&x, BinaryNode * & t);
void remove(const Comparable & x, BinaryNode * & t);
BinaryNode * findMin(BinaryNode *t) const
{
if (t == nullptr)
return nullptr;
if (t->left == nullptr)
return t;
return findMin(t->left);
}
BinaryNode * findMax(BinaryNode *t) const
{
if (t != nullptr)
while (t->right != nullptr)
t = t->right;
return t;
}
bool contains(const Comparable & x, BinaryNode *t)const;
void makeEmpty(BinaryNode * &t);
void printTree(BinaryNode *t, std::ostream & out)const;
BinaryNode * clone(BinaryNode *t)const
{
if (t == nullptr)
return nullptr;
else
return new BinaryNode(t->element, clone(t->left), clone(t->right));
}
};
/*
* 向子树插入元素的内部方法。
* x 是要插入的项。
* t 为该子树的根节点。
* 置子树的新根。
*/
template<typename Comparable>
inline void BinarySearchTree<Comparable>::insert(const Comparable & x, BinaryNode *& t)
{
if (t == nullptr)
t = new BinaryNode(x, nullptr, nullptr);
else if (x < t->element)
insert(x, t->left);
else if (x > t->element)
insert(x, t->right);
else
; // 重复元什么也不做
}
template<typename Comparable>
inline void BinarySearchTree<Comparable>::insert(const Comparable && x, BinaryNode *& t)
{
if (t == nullptr)
t = new BinaryNode(std::move(x), nullptr, nullptr);
else if (x < t->element)
insert(std::move(x), t->left);
else if (x > t->element)
insert(std::move(x), t->right);
else
; //重复元,什么也不做
}
/*
* 使子树为空的内部方法。
*/
template<typename Comparable>
inline void BinarySearchTree<Comparable>::makeEmpty(BinaryNode * &t)
{
if (t != nullptr)
{
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
}
t = nullptr;
}
/*
* 从一棵树删除一项的内部方法。
* x 是要被删除的项。
* t 为该子树的根节点。
* 置该子树的新根。
*/
template<typename Comparable>
void BinarySearchTree<Comparable>::remove(const Comparable & x, BinaryNode *& t)
{
if (t == nullptr)
return; //没找到,什么也不做
if (x < t->element)
remove(x, t->left);
else if (t->element < x)
remove(x, t->right);
else if (t->left != nullptr && t->right != nullptr) //有两个儿子
{
t->element = findMin(t->right)->element;
remove(t->element, t->right);
}
else {
BinaryNode *oldNode = t;
t = (t->left != nullptr) ? t->left : t->right;
delete oldNode;
}
}
/*
以排序的顺序打印根在t处的子树的内部方法。
*/
template<typename Comparable>
inline void BinarySearchTree<Comparable>::printTree(BinaryNode * t, std::ostream & out) const
{
if (t != nullptr)
{
printTree(t->left, out);
out << t->element << endl;
printTree(t->right, out);
}
}
/*
* 测试一项是否在子树上的内部方法。
* x 是要查找的项。
* t 是作为该子树的根的节点。
*/
template<typename Comparable>
inline bool BinarySearchTree<Comparable>::contains(const Comparable & x, BinaryNode * t) const
{
if (t == nullptr)
return false;
else if (x < t->element)
return contains(x, t->left);
else if (x> t->element)
return contains(x, t->right);
else
return true;
}
main.c 测试主程序:
#include <iostream>
#include <vector>
#include "binarySearchTree.h"
using namespace std;
int main()
{
vector<int> num = { 6,2,8,1,4,3,5 };
BinarySearchTree<int> bst;
/*生成二叉查找树*/
// for(auto & note: num)
// bst.insert(note);
int x;
cout << "请输入数字:"<< endl;
while (cin >> x && x)//以0作为输入结束
{
bst.insert(x);
}
cout << " 打印二叉树: " << endl;
bst.printTree();
cout << "删除小于5的数:" << endl;
for (size_t i=0; i < 5; ++i)
bst.remove(i);
cout << "删除后的二叉树:" << endl;
bst.printTree();
cout <<" 测试查找contains()函数:" << endl;
cout << bst.contains(7) << endl;
cout << "测试最大最小值:" << endl;
cout << "最大值: " << bst.findMax() << endl;
cout << "最小值: " << bst.findMin() << endl;
cout << "测试拷贝构造函数: " << endl;
BinarySearchTree<int> bst2(bst);
bst2.printTree();
cout << "测试赋值操作: " << endl;
BinarySearchTree<int> bst3;
bst3 = bst2;
bst3.printTree();
cout <<"所有测试完成!"<< endl;
return 0;
}