[Data Structure] 重新实现BinaryTree类模板

二叉树(binary tree)是有限个元素的集合(允许为空)。当二叉树非空时,其中有一个称为根的元素,余下的元素(如果有的话)被组成 2个二叉树,分别称为左子树和右子树。

和树的主要区别是:

二叉树可以为空,树不能为空。

二叉树中每个元素都恰好有两棵子树(其中一个或两个可能为空)。而树中每个节点有若干子树且没有左右这样的区分。

包含n个节点的二叉树的高度最大为n,最小为log(n+1),树的高度和节点个数无关。

 二叉树常用的描述方式是链表形式,每个元素都用一个节点结构体来表示,节点包括两个指针LeftChild和RightChild分别指向左子树和右子树,除此两个指针外,每个节点还有一个data表示当前元素的数值。

节点的默认构造函数构造一个空节点,不仅不存在data值且左右子树都为空;带有一个int型参数的构造函数,构造当前节点,但是左右子树为空;第三种情况是参数带有一个int值和两个子树指针。

//1.默认构造函数
BinaryTreeNode() { _LeftChild = _RightChild = 0; }

//2.带有一个数值的构造函数	
BinaryTreeNode(const T& value) {	
    _data = value;
	_LeftChild = _RightChild = 0;
}

//3.带有数值和左右子树指针的构造
BinaryTreeNode(const T& value, BinaryTreeNode *l, BinaryTreeNode *r) {
	_data = value;
	_LeftChild = l;
	_RightChild = r;
}

二叉树的主要操作包括构造树、计算高度、计算节点数、复制、遍历、删除整棵树、插入节点等等。

1.二叉树的构造

创建一个空节点作为根节点,即创建一个空树。

2.计算高度

最常见的方式是利用递归分别计算左右子树的高度,取大者加一就是当前树的高度了。

//树的高度
size_type Height() const {
	return Height(_root);
}

重载了一个私有的成员函数 ,递归计算节点的左右子树的高度,并比较两者的大小。

//节点的高度
size_type Height(BinaryTreeNode<value_type> *node) const {
	if (!node)
		return 0;
	size_type lh = Height(node->_LeftChild); //递归计算左子树高度
	size_type rh = Height(node->_RightChild); //递归计算右子树高度
	return (lh > rh) ? (lh + 1) : (rh + 1);
}

3.遍历

树的三种遍历,都采用递归的思想实现,以前序遍历为例:

//对二叉树进行前序遍历
void PreOrder(void(*Visit) (BinaryTreeNode<value_type> *u), BinaryTreeNode<value_type> *node) {
	if (node) {
		Visit(node); //对根节点进行处理
		PreOrder(Visit, node->_LeftChild); //前序遍历左子树
		PreOrder(Visit, node->_RightChild); //前序遍历右子树
	}
}

引入了一个函数指针参数,供其他需要遍历的功能使用,例如统计节点数、删除树和打印节点等的时候,调用不同的处理根节点的方法就可以了。

除此以外还有一种层序遍历,和其他三种有点差别。 

4.统计节点数

肯定要遍历整个树,这里三种遍历方式结果一样,以前序遍历为例:

//节点个数
size_type size() {
	_count = 0;
	PreOrder(Add, _root);
	return _count;
}

其中Add是一个私有的静态成员函数,访问到某个节点时,将_count参数加1。

5.删除整棵树

需要先删除子节点再删除父节点,所以这里只能采用后序遍历逐个节点销毁的方式:

//删除一棵树
void destroy() {
	PostOrder(DeleteNode, _root); //后序遍历并逐个删除节点
	_root = nullptr;
}

其中DeleteNode是一个私有的静态成员函数,访问到某个节点时,将其内存回收。

6.插入节点

需要注意的是需要判断节点是否为空,还要做一次判断将新节点插入左右子节点位置:

//插入节点
void insert(BinaryTreeNode<value_type> *node, const value_type &value) {
	if (!node) {
		node = new BinaryTreeNode(value);
		return;
	}

	if (value < node->_data) {
		insert(node->_LeftChild, value);
	} else {
		insert(node->_RightChild, value);
	}
}

  7.根据值搜索节点

bool find(const value_type value) const {
	return find(value, _root);
}

重载一个私有的静态成员函数,递归的在左右子树中搜索当前的数值:

bool find(const value_type value, BinaryTreeNode<value_type> *node) const {
	if (!node)
		return false;
	if (node->_data == value)
		return true;

	return find(value, node->_LeftChild) || find(value, node->_RightChild);
}

需要注意判断是否递归到叶子节点。

二叉树功能测试代码

int main()
{
	BinaryTree<int> t, t1, t2, t3;

	t2.MakeTree(1, t, t);
	t3.MakeTree(2, t, t);
	t1.MakeTree(3, t2, t3);
	t2.MakeTree(4, t1, t);

	cout << "树的节点数:" << t2.size() << endl;

	cout << "前序遍历: " << endl;
	t2.DisplayPreOrder();
	cout << "中序遍历: " << endl;
	t2.DisplayInOrder();
	cout << "后序遍历: " << endl;
	t2.DisplayPostOrder();

	cout << "树的高度: " << t2.Height() << endl;

	cout << endl;
	if (t2.find(3)) {
		cout << "找到节点" << endl;
	} else {
		cout << "没找到节点" << endl;
	}

	cout << endl;
	t2.destroy(); //删除树
	if (t2.empty()) {
		cout << "树已被删除" << endl;
	}

	cout << "树的高度: " << t2.Height() << endl;

	system("pause");
	return 0;
}

测试结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值