二叉搜索樹的實現,以及總要想的函數傳參和返回值......
一個關於返回值引用的鏈接:
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的結點之前進行處理。這種遍歷不用遞歸實施,用隊列來做,而不是遞歸所用的棧
};