二叉树BinaryTree的C++实现

二叉树BinaryTree的C++实现

需要具备的基础知识

  • C++语法和STL

  • 类模板和函数模板

  • 二叉树的概念

  • 二叉树的先序遍历、中序遍历和后序遍历

需求分析

  • 打印:输出树的所有节点数据,如print(),无需输入参数

    • 递归法先序遍历、中序遍历和后序遍历

    • 迭代法(循环)遍历,stack

  • 查找:输入val,查找树中是否有相同的节点数据(假设无重复数据),找到则返回目标节点的地址;未找到则返回NULL

  • 插入:先查找目标节点,未找到返回false;找到目标节点,明确在目标节点的左或右插入新的节点;左插入新节点前判断目标节点的左指针域是否为NULL,NULL则插入,!NULL返回false;右插入新节点前判断目标节点的左指针域是否为NULL,NULL则插入,!NULL返回false

二叉树的节点定义

定义一个TreeNode的结构体模板,包括数据域、左指针域和右指针域,在结构体中完成节点的构造。

//
//定义一个树的节点模板
//
template<class Elem>
struct TreeNode{
	Elem data;
	TreeNode<Elem> *left;
	TreeNode<Elem> *right;
	TreeNode(Elem val){
		data = val;
		left = right = nullptr;
	}
};

二叉树的定义

定义一个二叉树BinTree的模板类,私有成员为树的根节点m_root,无参构造,有参构造。

//
//定义一个二叉树的模板类
//
template<class Elem>
class BinTree{
public:
	BinTree(){ 
		m_root = nullptr;
	}
	BinTree(Elem val){
		m_root = new TreeNode<Elem>(val);
	}
	~BinTree(){

	}
private:
	TreeNode<Elem> *m_root;
};

打印需求实现

打印树的数据需要遍历所有节点,利用递归法或迭代法都能实现,同时要注意对外提供给用户的公有函数接口要简单。

  • 利用递归法实现打印功能
//函数声明
//受保护的内部函数
protected:
    void rPreOrder(TreeNode<Elem> *root) const;
    void rInOrder(TreeNode<Elem> *root) const;
//对外接口函数调用内部函数
public:
    void rPrint() const;
//
//打印函数实现
//
template<class Elem>
void BinTree<Elem>::rPreOrder(TreeNode<Elem> *root) const{
	if (root == nullptr){
		return ;
	}
	cout << root->data << ' ';
	rPreOrder(root->left);
	rPreOrder(root->right);
}

template<class Elem>
void BinTree<Elem>::rInOrder(TreeNode<Elem> *root) const{
	if (root == nullptr){
		return ;
	}
	rInOrder(root->left);
	cout << root->data << ' ';
	rInOrder(root->right);
}

template<class Elem>
void BinTree<Elem>::rPrint() const{
	cout << "递归先序遍历:";
	rPreOrder(m_root);
	cout << endl;

	cout << "递归中序遍历:";
	rInOrder(m_root);
	cout << endl;
}

查找需求实现

输入val,查找树中是否有相同的节点数据(假设无重复数据),找到则返回目标节点的地址;未找到则返回NULL

//函数声明
//受保护的内部函数
protected:
    TreeNode<Elem>* rFindVal(TreeNode<Elem> *root, Elem val) const;
//对外接口函数调用内部函数
public:
    TreeNode<Elem>* findVal(Elem val) const;
//
//查找函数实现
//
template<class Elem>
TreeNode<Elem>* BinTree<Elem>::rFindVal(TreeNode<Elem> *root, Elem val) const{
	if(!root){
		return nullptr;
	}
	//先找根节点的数据是否和val相同
	if(val == root->data){
		return root;
	}
	//再从左子树中查找
	TreeNode<Elem> *objectNode = rFindVal(root->left, val);
	//若在左子树中找到目标节点,返回节点地址;若在左子树中没有找到目标节点,从右子树中查找
	return objectNode ? objectNode : rFindVal(root->right, val);
}
template<class Elem>
TreeNode<Elem>* BinTree<Elem>::findVal(Elem val) const{
	//调用内部定义的rFindVal
	return rFindVal(m_root, val);
}

插入需求实现

  • 先查找目标节点,未找到返回false;

  • 找到目标节点,明确在目标节点的左或右插入新的节点;

    • 左插入新节点前判断目标节点的左指针域是否为NULL,NULL则插入,!NULL返回false;

    • 右插入新节点前判断目标节点的左指针域是否为NULL,NULL则插入,!NULL返回false。

//函数声明
public:
    bool insert(Elem obj, int LeftOrRight, Elem val);;
//
//插入函数实现
//
template<class Elem>
bool BinTree<Elem>::insert(Elem obj, int LeftOrRight, Elem val){
	//调用查找函数查找目标节点obj,找到返回地址,没有找到返回false
	TreeNode<Elem> *objectNode = findVal(obj);
	//如果没有找到目标节点obj,返回false
	if (!objectNode){
		return false;
	}
	//找到目标节点后,根据参数LeftOrRight确定在目标节点的左或右插入新的节点
	if (LeftOrRight == 0){
		//如果目标节点存在左节点,不能插入新节点,返回false
		if (objectNode->left){
			return false;
		}
		objectNode->left = new TreeNode<Elem>(val);
	}
	else{
		//如果目标节点存在右节点,不能插入新节点,返回false
		if (objectNode->right){
			return false;
		}
		objectNode->right = new TreeNode<Elem>(val);
	}
	return true;
}

代码测试

int main(){
	BinTree<int> bt(11);
	bt.insert(11, 0, 22);
	bt.insert(11, 1, 33);
	bt.insert(22, 0, 44);
	bt.insert(22, 1, 55);
	bt.insert(33, 0, 66);
	bt.insert(33, 1, 77);
	bt.rPrint();
}

后续会介绍二叉搜索树和平衡二叉树,敬请期待。

完整的代码后面会上传到github供参考。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值