Day6:无序二叉树的插入以及遍历(前/中/后序)

/*基础概念参照:*/

数据结构 --- c语言二叉树基础(无序二叉树)https://blog.csdn.net/weixin_60569662/article/details/123083815

pre:树框架的构建

template<class T>
struct Node
{
	T   data;
	Node* pLeft;//左孩子	
	Node* pRight;//右孩子

	Node(const T& data)
	{
		this->data = data;
		pLeft = pRight = nullptr;
	}
};
template<class T>
class Tree
{
public:
	Tree() { pRoot = nullptr; }
	~Tree() { _clear(pRoot); }
	void clear(Node<T>*pDel) 
	{
		_clear(pDel)
	}
	bool insert(const T& data)
	{return _insert(data,pRoot); }
	void travel(int type);//-1前序遍历 0中序遍历 1后序遍历

private:	
	Node<T>* pRoot;
private:    //也可以用二级指针完成,引用更常用一点
	bool _insert(const T& data,Node<T>*&pRoot);
	void _clear(Node<T>* pDel);

	//先序
	void _preTravel(TreeNode<T>* root);
	//中序
	void _midTravel(TreeNode<T>* root);
	//后序
	void _lstTravel(TreeNode<T>* root);
};

一、无序二叉树的插入

注意:①利用二叉树的递归特性(不断成为新的根节点

           ②利用Ddata来限制是插左孩子还是右孩子->注意判断放置的位置!!同时利用bool返回值来控制。

           ③第一个if插成功了,记得return true;

template<class T>
bool Tree<T>::_insert(const T& data, Node<T>*& pRoot)
{
	//递归终止条件
	if (pRoot == nullptr)
	{
		Node<T>* pNew = new Node<T>(data);
		pRoot = pNew;
		return true;
	}
	//控制插入左孩子还是右孩子
	if (Ddata == pRoot->data)return false;
	//递归
	if (_insert(data, pRoot->pLeft))return true;
	return _insert(data, pRoot->pRight);
}

 测试代码:

	Tree<int> mytree;
	int arr[] = { 1,2,Ddata,4,5,Ddata,Ddata,Ddata,3,Ddata,6,Ddata,7,Ddata,Ddata};
	for (auto v : arr)
	{
		mytree.insert(v);
	}

 实现的二叉树如下图:

 二、无序二叉树的遍历:

1.简述:

  • 前序遍历:根在前面,根左右

  • 中序遍历:左根右

  • 后序遍历:根在后面,左右根

2.以上图的二叉树为例,三种结果为:

        前序遍历
        1 2 4 5 3 6 7
        中序遍历
        2 5 4 1 3 6 7
        后序遍历
        5 4 2 7 6 3 1

3.利用递归,代码的实现十分简洁   

template<class T>
void Tree<T>::travel(int type)
{
	switch (type)
	{
	case -1:
		cout << "前序遍历" << endl;
		_preTravel(pRoot); break;
	case 0:
		cout << "中序遍历" << endl;
		_midTravel(pRoot); break;
	case 1:
		cout << "后序遍历" << endl;
		_lstTravel(pRoot); break;
	}
	cout << endl;
}
template<class T>
void Tree<T>::_preTravel( Node<T>*& root)
{//前序遍历:根左右
	if (root == nullptr)return;//递归终止条件一定不能忘记
	cout << root->data << " ";
	_preTravel(root->pLeft);
	_preTravel(root->pRight);
}
template<class T>
void Tree<T>::_midTravel( Node<T>*& root)
{//前序遍历:左根右
	if (root == nullptr)return;
	_midTravel(root->pLeft);
	cout << root->data << " ";
	_midTravel(root->pRight);
}
template<class T>
void Tree<T>::_lstTravel( Node<T>*& root)
{//前序遍历:左右根
	if (root == nullptr)return;
	_lstTravel(root->pLeft);
	_lstTravel(root->pRight);
	cout << root->data << " ";
}

 注:因为有叶子结点(Ddata=9999)作为切换左右孩子的条件->所以,在此输出的时候,在上面的代码可以再添加一下控制,不让叶子结点的data输出。(为了代码的简洁可读性,此处没加)

三、无序二叉树遍历的理论分析

1.利用递归的思想,里面最先出来+前中后序遍历的限制,就很容易分析出!!!

        前序遍历
        1 2 4 5 3 6 7
        中序遍历
        2 5 4 1 3 6 7
        后序遍历
        5 4 2 7 6 3 1

 时时自测一下,以中序为例,很容易犯错的是,F在H前面,递归到最深处,也得满足左(H)根(F)右,H必定在F的左侧。

2.已知中序+前or后可推导出原树

    已知 中序遍历 和 先序遍历  能推导出  后序遍历
    已知 中序遍历 和 后序遍历  能推导出  先序遍历
    已知 先序遍历 和 后序遍历 , 推导不出

 其他参考:二叉树的前序、中序、后序遍历(个人笔记) - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/73438175

四、无序二叉树的释放

template<class T>
void Tree<T>::_clear(Node<T>*& pDel)
{
	//错误思路:遍历一遍,依次释放
	//利用递归特性:逐一释放
	if (pDel == nullptr)return;//注意递归终止条件
	_clear(pDel->pLeft);
	_clear(pDel->pRight);
	delete pDel;
	pDel = nullptr;
}

利用递归特性->递归释放!!!!!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Ocean__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值