二叉搜索樹的一些實現

二叉搜索樹的實現,以及總要想的函數傳參和返回值......

一個關於返回值引用的鏈接:

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的結點之前進行處理。這種遍歷不用遞歸實施,用隊列來做,而不是遞歸所用的棧
};



發佈了56 篇原創文章 · 獲贊 9 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章