二叉树的实现与递归遍历

前情提要:

        我们首先谈一谈什么是二叉树

        二叉树,是一种特殊的树结构。而树结构,就是由一个主干和多个枝干组成的结构。我们平时在公司的职位就是一种典型的树结构,老板是根,员工是叶子,中间的管理人员是组成树的枝干,把这棵树翻转过来,我们就可以得到一张表示树的示例图:

         树有一个非常有意思的点:树的子树还是一棵树

        拿我们的李组长举例子:

         李组长带领的打工仔甲、“你”和隔壁老王,又组成了一棵树。那么现在问题来了,“你”算不算一棵树呢?

        答案是肯定的。不过“你”是一颗特殊的树。

        下面介绍的二叉树,也是一种特殊的树,它有以下特点:每个结点最多只能有两棵子树,且有左右之分 。

二叉树定义

        二叉树是n个有限元素的集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树右子树的二叉树组成。是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个结点。

二叉树性质:

(1) 在二叉树的第i层上至多有2 ^(i-1)个节点(i>=1)

(2) 深度为k的二叉树最大节点数为2^k-1个节点(k>=1)

  •         一颗深度为k且有2k-1个节点的二叉树称为 满二叉树
  •         可以对 满二叉树 进行连续编号,约定编号从根节点起,自上而下,自左至右
  •         深度为k的,有n个节点的二叉树,当且仅当其每一个节点斗鱼深度为k的满二叉树中编号          从1至n的节点一一对应时,称之为 完全二叉树

(3) 对任意一颗二叉树T,如果其终端节点为n0,度为2的节点数为n2,则n0=n2+1

(4)    具有n个节点的完全二叉树(其深度为 floor(log2(n))+1)的节点按层序编号,对任意节点i(1<=i<=n)  i>1时,其双亲节点为floor(i/2)

【注】:floor 为向下取整

二叉树的三种遍历

        现在有一颗二叉树如下图:

         我们规定以下三种方式来遍历这一棵二叉树:

         先(根)序遍历、中(根)序遍历、后(根)序遍历 

        我们用先(根)序遍历举例子,顾名思义,先根,就是先访问根节点,然后访问其左孩子节点、右孩子节点

        图中用先序遍历结果就是:老板 、张组长、 打工仔乙 、李组长、 你 、隔壁老王

        中序后序遍历如法炮制即可~

二叉树的数据结构以及简单操作(递归)的C++实现

        简单回顾了二叉树的基本概念以后,我们试着实现一下二叉树的数据结构,以及用用最容易理解的递归来实践一下二叉树的最简单操作。

        这里用智能指针shared_ptr优化了leetCode最常见的二叉树数据结构版本。

头文件:

#ifndef _TREE_H_
#define _TREE_H_
#include <memory>
#include <vector>
#include <iostream>
/*************************************************

class  :二叉树节点

brief  :Definition for a binary tree node.( -- leetCode)
 
author :zhoufang

date 2021/11/22

**************************************************/
namespace BinaryTree {
    //二叉树的智能指针版本
	struct TreeNode {
		int val;             //当前节点的值
		std::shared_ptr<TreeNode> left;    //左孩子节点
		std::shared_ptr<TreeNode> right;   //右孩子节点
		/* 重载的三个构造函数*/
		TreeNode() :val(0), left(nullptr), right(nullptr) {}
		TreeNode(int val) :val(val), left(nullptr), right(nullptr) {}
		TreeNode(int val, std::shared_ptr<TreeNode> left, std::shared_ptr<TreeNode> right) : val(val), left(left), right(right) {}
	};
	using TreeNodePtr = std::shared_ptr<TreeNode>;
	/**
	* @brief 显示二叉树当前节点值
	* @param root 二叉树根节点
	*/
	void disPlayBiTree(const TreeNodePtr& root);

	/**
	* @brief 递归先序创建二叉树
	* @param root 二叉树根节点
	* @return   是否成功创建二叉树
	*/
	bool createBinaryTree(TreeNodePtr& root);
	//bool createBinaryTree(TreeNodePtr &root,const std::vector<int>& vals);

	/**
	* @brief (递归)先序遍历二叉树
	* @param root  二叉树根节点
	*/
	void preOrderTraverse(const TreeNodePtr& root);

	/**
	* @brief (递归)中序遍历二叉树
	* @param root  二叉树根节点
	*/
	void inOrderTraverse(const TreeNodePtr& root);
	/**
	* @brief (递归)后序遍历二叉树
	* @param root  二叉树根节点
	*/
	void postOrderTraverse(const TreeNodePtr& root);
}
#endif//!_TREE_H_if

cpp:

#include <stack>
#include "Tree.h"
using namespace std;


void BinaryTree::disPlayBiTree(const TreeNodePtr& root)
{
    if(!root)return;    
	cout << root->val;
}
bool BinaryTree::createBinaryTree(BinaryTree::TreeNodePtr& root)
{
	int value;
	cin >> value;
	if (value == 0)
	{
		root = nullptr;
	}
	else
	{
		root->val = value;
		BinaryTree::createBinaryTree(root->left = std::make_shared<BinaryTree::TreeNode>());
		BinaryTree::createBinaryTree(root->right = std::make_shared<BinaryTree::TreeNode>());
	}
	return true;
}



void BinaryTree::preOrderTraverse(const BinaryTree::TreeNodePtr& root)
{
	if (root)//根节点存在
	{
		//打印根节点存储值
		disPlayBiTree(root);
		//先序遍历左子树
		BinaryTree::preOrderTraverse(root->left);
		//先序遍历右子树
		BinaryTree::preOrderTraverse(root->right);
	}
}

void BinaryTree::inOrderTraverse(const TreeNodePtr& root)
{
	if (root)//根节点存在
	{
		//中序遍历左子树
		BinaryTree::inOrderTraverse(root->left);
		//打印根节点存储值
		disPlayBiTree(root);
		//中序遍历右子树
		BinaryTree::inOrderTraverse(root->right);
	}
}

void BinaryTree::postOrderTraverse(const TreeNodePtr& root)
{
	if (root)//根节点存在
	{
		//后序遍历左子树
		BinaryTree::postOrderTraverse(root->left);
		//后序遍历右子树
		BinaryTree::postOrderTraverse(root->right);
		//打印根节点存储值
		disPlayBiTree(root);
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值