二叉搜索树的实现,以及总要想的函数传参和返回值......
一个关于返回值引用的链接:
http://blog.csdn.net/keyouan2008/article/details/5741917
//二叉排序树,每个结点的左子树都比这个结点小,右子树比这个结点大
//构造,析构,找最大,最小,插入,删除,找树中是否含有某一个结点
template <typename Comparable>
class BinarySearchTree
{
public: //用public的函数调用private的函数,有的如果发现公有的函数没有实现,那么缺的就是一个它调用私有函数的过程,比如makeEmpty()没有写,但是就调用的是私有函数的void makeEmpty(BinaryNode* & t);
/*
返回指向函数调用前就已经存在的对象的引用是正确的。当不希望返回的对象被修改时,返回const引用是正确的。
关于返回的类型:
1)主函数main的返回值:这里提及一点,返回0表示程序运行成功。
2)返回非引用类型:函数的返回值用于初始化在跳用函数出创建的临时对象。用函数返回值初始化临时对象与用实参初始化形参的方法是一样 的。如果返回类型不是引用,在调用函数的地方会将函数返回值复制给临时对象。且其返回值既可以是局部对象,也可以是求解表达式的结果。
3)返回引用:当函数返回引用类型时,没有复制返回值。相反,返回的是对象本身。
*/
BinarySearchTree(); //构造函数
BinarySearchTree(const BinarySearchTree &rhs); //拷贝构造函数
~BinarySearchTree(); //析构函数
const Comparable & findMax() const;
const Comparable & findMin() const;
bool contains(const Comparable &x) const; //查找树里有没有x这个数的结点
bool isEmpty() const;
void printTree() const;
void makeEmpty(); //析构用的
void insert(const Comparable &x);
void remove(const Comparable &x);
const BinarySearchTree & operator=(const BinarySearchTree & rhs); //运算符重载
private:
struct BinaryNode //树里的每个结点
{
Comparable element;
BinaryNode *left; //二叉树左右子树
BinaryNode *right;
BinaryNode(const Comparable & theElement, Binary *lt, Binary *rt) :element(theElement), left(lt), right(rt){}
};
BinaryNode *root;
//t代表的是子树的根,比如下面的insert就是把x插入到以t为根结点的子树里
void insert(const Comparable &x, BinaryNode* & t)const; //不知道对不对......原来的树的结点不能变,所以后面的const有,但是插入之后树变了,所以返回值不能是const,所以前面的const没有
void remove(const Comparable &x, BinaryNode* & t)const;
BinaryNode* findMin(BinaryNode *t) const; //找以这个为根的子树的最大的结点
BinaryNode* findMax(BinaryNode *t) const;
/*自己的关于传入参数的理解:
传进去新的就用&,传入引用,但是如果是一开始就有的,不是新的,就不用&了,
所以上面是BinaryNode* & t,下面就是BinaryNode* t。
觉得传值,如果涉及到改动(就是说,要改动传进来的参数,数值,位置之类的),
就是类似于,a和b交换的那种问题(改动传进来的参数的数值),
还有上面的要把结点插进去(改动传进来的参数的位置),
能用引用用引用,因为引用只是起别的名字,这样子不会产生新的内存。
但是下面的,只是根据传进来的参数找东西,而不是要改动些东西,就不用&了
*/
bool contains(const Comparable & x, BinaryNode * t) const; //const Comparable & x,呃,这种类型的,就记住吧,见得比较多...大家都这么用...
void makeEmpty(BinaryNode* & t); //上面的析构调用这个析构来搞
void printTree(BinaryNode *t) const;
BinaryNode* clone(BinaryNode *t)const;
//具体的函数内容
bool contains(const Comparable &x) const
{
return contains(x, root);
}
bool contains(const Comparable & x, BinaryNode * t) const
{
if (t == NULL)
return false;
else if (x < t->element)
return contains(x, t->left);
else
return contains(x, t->right);
else
return true;
}
void insert(const Comparable &x)
{
insert(x, root);
}
void insert(const Comparable &x, BinaryNode* & t)const
{
if (t == NULL)
{
t = new BinaryNode(x, NULL,NULL);
}
else
{
if (x < t->element)
{
insert(x, t->left);
}
else if (x > t->element)
{
insert(x, t->right);
}
}
}
BinaryNode* findMax(BinaryNode *t) const
{
if (t == NULL)
return NULL;
else if (t->right == NULL)
return t;
else
return findMax(t->right);
}
BinaryNode* findMin(BinaryNode *t) const
{
if (t == NULL)
return NULL;
while (t->left != NULL)
t = t->left;
return t;
}
void remove(const Comparable &x);
void remove(const Comparable &x, BinaryNode* & t)const;
{
if (t == NULL)
return;
if (x < t->element)
remove(x, t->left);
else if (x>t->element)
remove(x, t->right);
else if (t->left != NULL&&t->right != NULL)
{
t->element = findMin(t->right)->element;
remove(t->element, t->right);
}
else //这里注意,删除结点,先用一个指针指向这个结点,然后把新结点弄过来,再删除老的结点
{
BinaryNode *oldNode = t;
t = (t->left != NULL) ? t->left : t->right;
delete oldNode;
}
}
~BinaryNode()
{
makeEmpty();
}
void makeEmpty(BinaryNode* & t)
{
if (t != NULL)
{
remove(t->left);
remove(t->right);
delete t;
}
t = NULL; //把t的指针指向空
}
/**
*深拷贝
*/
const BinarySearchTree & operator=(const BinarySearchTree &rhs)
{
if (this != &rhs)
{
makeEmpty();
root = clone(rhs.root); //深拷贝不是让两个指向一个空间,就是两个指针指向一棵树,而是弄出来两棵树
}
return *this;
}
BinaryNode * clone(BinaryNode *t) const
{
if (t == NULL)
return NULL;
return new BinaryNode(t->element, clone(t->left), clone(t->right));
}
//中序遍历,打印一棵树
void printTree(ostream & out = cout) const
{
if (isEmpty())
out << "Empty tree" << endl;
else
printTree(root, out);
}
void printTree(BinaryNode *t, ostream & out) const
{
if (t != NULL)
{
printTree(t->left, out);
out << t->element << endl;
printTree(t->right, out);
}
}
//后序遍历,求树的高度
int height(BinaryNode *t)
{
if (t == NULL)
return -1;
else
return 1 + max(height(t->left), height(t->right));
}
//还有一种遍历,叫做层序遍历,就是深度为d的结点要在深度为d+1的结点之前进行处理。这种遍历不用递归实施,用队列来做,而不是递归所用的栈
};