學習日記——二叉樹以及搜索二叉樹的實現

說明

這是國外經典教材Data structures and Program Design In C++數據結構與程序設計C++版中的二叉樹實現方法,作者是Robert.Kruse&Alexander J.Ryba,由錢麗萍譯,本來是課本上的源代碼,我一開始是自己照搬下來的,後來對複雜的代碼進行部分的優化,把幾行代碼變成了一行或者少一點的

註釋

對於每個函數和每行代碼的理解我已經敲在相應的代碼行後邊或下邊,可能看起來比較冗雜,但這不是交的作業,我就根據自己最喜歡的方式來了,也不知道真正好的習慣是怎麼樣的,那就直接上代碼吧

#include<iostream>
using namespace std;
enum Error_code { success, fail, not_present, duplicate_error };
//二叉樹結點*******************************************
template<class entry>
struct Binary_node
//結點結構體,包含數據、左右指針、構造函數、複製構造函數
{
	entry data;
	Binary_node<entry>*left;
	Binary_node<entry>*right;
	Binary_node();
	Binary_node(const entry&x);
	//常引用相當於const entry*const x
	//不僅僅是x的地址不可修改,其指向的內存空間也不可修改
};
template<class entry>
Binary_node<entry>::Binary_node()
{
	data = 0;
	left = right = NULL;//構造函數,把指針初始化
}
template<class entry>
Binary_node<entry>::Binary_node(const entry&x)
{
	data = x;
	left = right = NULL;//初始化內部三個形參
}

//二叉樹**********************************************
template<class entry>
class Binary_tree
{
public:
	void recursive_inorder(Binary_node<entry>*sub_root, void(*visit)(entry&));//遞歸中序遍歷
	//函數指針,用於調用函數和做函數的參數
	void inorder(void(*visit)(entry&x)) { recursive_inorder(root, visit); }//外層函數調用遞歸中序遍歷
	void recursive_preorder(Binary_node<entry>*sub_root, void(*visit)(entry&));//遞歸先序遍歷
	void preorder(void(*visit)(entry&x)) { recursive_preorder(root, visit); }
	void recursive_postorder(Binary_node<entry>*sub_root, void(*visit)(entry&));//遞歸後序遍歷
	void postorder(void(*visit)(entry&x)) { recursive_postorder(root, visit); }
	int size()const;
	//常函數,函數值不會發生變化
	int recursive_size(Binary_node<entry>*sub_root)const;//遞歸求大小

	int height()const;
	int recursive_height(Binary_node<entry>*sub_root)const;//遞歸求高度

	void insert(const entry&x);
	void recursive_insert(Binary_node<entry>*&sub_root, const entry&x);

	void clear();
	void recursive_clear(Binary_node<entry>*&sub_root);

	Binary_tree() { root = NULL; }
	~Binary_tree();

	Binary_tree(const Binary_tree<entry>&original);
	Binary_node<entry>*recursive_copy(Binary_node<entry>*sub_root);

	Binary_tree&operator=(const Binary_tree<entry>&original);
private:
	Binary_node<entry> *root;
};
template<class entry>
void Binary_tree<entry>::recursive_inorder(Binary_node<entry>*sub_root, void(*visit)(entry&))
{//第一個參數爲根部指針,第二個參數爲輸出函數
	if (sub_root != NULL)
	{//什麼順序遍歷就把visit函數的調用放在哪,其他兩個遞歸就是先左後右
		recursive_inorder(sub_root->left, visit);
		(*visit)(sub_root->data);
		recursive_inorder(sub_root->right, visit);
	}
}
template<class entry>
void Binary_tree<entry>::recursive_preorder(Binary_node<entry>*sub_root, void(*visit)(entry&))
{
	if (sub_root != NULL)
	{
		(*visit)(sub_root->data);
		recursive_preorder(sub_root->left, visit);
		recursive_preorder(sub_root->right, visit);
	}
}
template<class entry>
void Binary_tree<entry>::recursive_postorder(Binary_node<entry>*sub_root, void(*visit)(entry&))
{
	if (sub_root != NULL)
	{
		recursive_postorder(sub_root->left, visit);
		recursive_postorder(sub_root->right, visit);
		(*visit)(sub_root->data);
	}
}
template<class entry>
int Binary_tree<entry>::size()const
{
	return recursive_size(root);
}
template<class entry>
int Binary_tree<entry>::recursive_size(Binary_node<entry>*sub_root)const
{
	if (sub_root == NULL)return 0;//根部爲空則返回0,此處爲遞歸基
	return 1 + recursive_size(sub_root->left) + recursive_size(sub_root->right);//每一個函數裏都有一個1,即根部不爲空時代表有一個結點
}
template<class entry>
int Binary_tree<entry>::height()const
{
	return recursive_height(root);
}
template<class entry>
int Binary_tree<entry>::recursive_height(Binary_node<entry>*sub_root)const
{//root處爲最高
	if (sub_root == NULL)return 0;
	int l = recursive_height(sub_root->left);//在函數內部仍會進行左右長度的計算,不會一直左一直右
	int r = recursive_height(sub_root->right);//其實不用聲明兩個形參,但是會寫很長的代碼
	return (l > r) ? (l + 1) : (r + 1);//大的再加一,就是最大高度,有最多結點
}
template<class entry>
void Binary_tree<entry>::insert(const entry&x)
{
	recursive_insert(root, x);
}
template<class entry>
void Binary_tree<entry>::recursive_insert(Binary_node<entry>*&sub_root, const entry&x)
{
	if (sub_root == NULL)sub_root = new Binary_node<entry>(x);//爲空就調用二叉樹的結點結構體的複製構造函數,新建一個
	else//總會在最低位置添加結點
		(recursive_height(sub_root->right) < recursive_height(sub_root->left))? recursive_insert(sub_root->right, x): recursive_insert(sub_root->left, x);
	//如果左邊高度大於右邊高度,就往右邊增加結點,根節點最高
}
template<class entry>
void Binary_tree<entry>::clear()
{
	recursive_clear(root);
}
template<class entry>
void Binary_tree<entry>::recursive_clear(Binary_node<entry>*&sub_root)//一個指針的引用
{
	Binary_node<entry>*temp = sub_root;
	if (sub_root == NULL)return;
	//從離根節點最遠的結點開始刪除,否則找不到沒有刪除的點
	recursive_clear(sub_root->left);
	recursive_clear(sub_root->right);
	sub_root = NULL;
	delete temp;
}
template<class entry>
Binary_tree<entry>::~Binary_tree()
{
	clear();
}
template<class entry>
Binary_tree<entry>::Binary_tree(const Binary_tree<entry>&original)
{
	root = recursive_copy(original.root);
}
template<class entry>
Binary_node<entry>*Binary_tree<entry>::recursive_copy(Binary_node<entry>*sub_root)
{
	if (sub_root == NULL)return NULL;
	Binary_node<entry>*temp = new Binary_node<entry>(sub_root->data);//把當前根節點的data給形參temp
	temp->left = recursive_copy(sub_root->left);//進行左節點的複製
	temp->right = recursive_copy(sub_root->right);
	return temp;
}
template<class entry>
//無模板時的運算符重載方式:    Binary_tree operator=(const Binary_tree&original)
//和外部聲明的開頭:
//Binary_tree模板  Binary_tree 模 板 ::operator=(const Binary_tree       &original
Binary_tree<entry>&Binary_tree<entry>::operator=(const Binary_tree<entry>&original)
{//運算符重載
	Binary_tree<entry>&new_copy(original);
	clear();
	root = new_copy.root;
	new_copy = NULL;
	return *this;
}
//二叉查找樹********************************************
template<class record>
class Search_tree :public Binary_tree<record>
{
public:
	Error_code insert(const record&new_data);
	Error_code search_and_insert(Binary_node<record>*&sub_root, const record&new_data);
	Error_code remove(const record&old_data);
	Error_code search_and_destroy(Binary_node<record>*&sub_root, const record&target);
	Error_code tree_search(record&target)const;
	Error_code remove_root(Binary_node<record>&sub_root);
	Binary_node<record>*Search_tree<record>::search_for_node(Binary_node<record>*sub_root, const record&target)const;
private:
};
//遞歸形式的插入函數
template<class record>
Error_code Search_tree<record>::insert(const record&new_data)
{
	return search_and_insert(root, new_data);
}
template<class record>
Error_code Search_tree<record>::search_and_insert(Binary_node<record>*&sub_root, const record&new_data)
{
	if (sub_root == NULL)
	{
		sub_root = new Binary_node<record>(new_data);
		return success;
	}
	else if (new_data < sub_root->data)
		return search_and_insert(sub_root->left, new_data);
	else if (new_data > sub_root->data)
		return search_and_insert(sub_root->right, new_data);
	else return duplicate_error;
}
/*
template <class Record>
Error_code Search_tree<Record> ::insert(const Record &new_data)
{
	if (root == NULL) {
		root = new Binary_node<Record>(new_data);
		return success;
	}
	Binary_node<Record> *sub_root = root, *parent;
	do {
		parent = sub_root;
		if (new_data < sub_root->data) sub_root = sub_root->left;
		else if (new_data > sub_root->data) sub_root = sub_root->right;
		else return duplicate_error;
	} while (sub_root != NULL);
	sub_root = new Binary_node<Record>(new_data);
	if (new_data < parent->data) parent->left = sub_root;
	else parent->right = sub_root;
}//插入函數的非遞歸形式
*/
template<class record>
Error_code Search_tree<record>::remove(const record&target)
{
	return search_and_destroy(root, target);
}
template<class record>
Error_code Search_tree<record>::search_and_destroy(Binary_node<record>*&sub_root, const record&target)
{
	if (sub_root == NULL || sub_root->data == target)
		return remove_root(sub_root);
	else if (target < sub_root->data)
		return search_and_destroy(sub_root->left, target);
	else
		return search_and_destroy(sub_root->right, target);
}
template<class record>
Error_code Search_tree<record>::remove_root(Binary_node<record>&sub_root)
{
	if (sub_root == NULL)
		return not_present;
	Binary_node<record>*to_delete = sub_root;
	if (sub_root->right == NULL)sub_root = sub_root->left;
	else if (sub_root->left == NULL)sub_root = sub_root->right;
	else
	{
		to_delete = sub_root->left;
		Binary_node<record>*parent = sub_root;
		while (to_delete->right != NULL)
		{
			parent = to_delete;
			to_delete = to_delete->right;
		}
		sub_root->data = to_delete->data;
		if (parent == sub_root)
			sub_root->left = to_delete;
		else parent->right = to_delete->left;
	}
	delete to_delete;
	return success;
}
template <class record>
Error_code Search_tree<record>::tree_search(record &target)const
{
	Error_code result = success;
	Binary_node<record>*found = search_for_node(root, target);
	if (found == NULL)
		result = not_present;
	else
		target = found->data;
	return result;
}
template<typename record>
Binary_node<record>*Search_tree<record>::search_for_node(Binary_node<record>*sub_root, const record&target)const
{
	if (sub_root == NULL || sub_root->data == target)
		return sub_root;
	else if (sub_root->data < target)
		return search_for_node(sub_root->right, target);
	else return search_for_node(sub_root->left, target);
}
template<class entry>
void visit(entry&x)
{
	cout << x << " ";
}

int main()
{
	//A
	//BC
	//DEF
	//後序打印,然後清空
	Binary_tree<char> tree;
	tree.insert('A');
	tree.insert('B');
	tree.insert('C');
	tree.insert('D');
	tree.insert('F');
	tree.insert('E');
	cout << endl << "先序遍歷" << endl;
	tree.preorder(visit);
	cout << endl << "中序遍歷" << endl;
	tree.inorder(visit);
	cout << endl << "後序遍歷" << endl;
	tree.postorder(visit);
	tree.clear();
	return 0;
}

剩下的一些bug

代碼應該說只是理論上的沒有問題,實際運行過程中我在VS2017版本遇到的問題有公有繼承Binary_tree類的搜索二叉樹時無法使用root這個私有數據,導致函數功能無法實現,還有就是二叉樹類的=運算符重載失敗,定義是沒有問題的,使用的時候就會出問題,感覺用了template之後bug會被減少,是那種調試不會出錯,但是使用不了的情況,如有dalao發現問題,請幫我指正一下,如果沒有,我就先把代碼放在這裏,以後自己慢慢改

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章