学习日记——二叉树以及搜索二叉树的实现

说明

这是国外经典教材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发现问题,请帮我指正一下,如果没有,我就先把代码放在这里,以后自己慢慢改

发布了4 篇原创文章 · 获赞 0 · 访问量 69

猜你喜欢

转载自blog.csdn.net/qq_43600632/article/details/103591297