文章目录

  • 前言
  • 创建二叉树
  • 先序遍历
  • 中序遍历
  • 后序遍历
  • 获取叶子节点个数
  • 获取树的高度
  • 测试代码

前言

现有如下二叉树:

关于二叉树的相关操作,我们能够发现二叉树从根节点到子节点,以及每个中间节点基本都能够拆分为若干个子节点的操作,且每个子节点的操作都和其头节点操作一致。
所以我们针对二叉树的操作都可以使用分治算+回溯/归并算法进行

完整测试代码见文末


创建二叉树

二叉树数据结构:

typedef struct tree
{char data;struct tree *left;struct tree *right;
}Tree,*TreeNode;

我们使用先序方式,创建如上二叉树:
输入如下: ABD***CE**FG***
创建过程

/*创建二叉树*/
void createTree(TreeNode *root) {char val = 0;cin >> val; //持续输入,直到完成一个二叉树的构建if (val == '*') {//输入为*则代表当前节点为空(*root) = NULL;} else {(*root) = (Tree *)malloc(sizeof(tree));if ((*root) == NULL) {cout << "create node failed " << endl;exit(-1);} else {(*root)->data = val;//为输入的节点赋值createTree(&(*root)->left);//分治左孩子节点createTree(&(*root)->right);//分治右孩子节点}}
}

先序遍历

先序遍历二叉树指:先遍历二叉树的根节点,再遍历当前根节点所有左子树,再遍历当前根节点所有右子树

因为这个过程针对子节点的遍历和根节点是没有任何区别的,所以可以使用分治进行处理

/*递归先序遍历*/
void preOrder(Tree *root) {if (root == NULL) {return;}cout << root->data;preOrder(root->left);preOrder(root->right);
}

同样可以使用栈进行非递归的先序遍历,即
栈可以保存遍历过程中的左节点,因为先序遍历是先访问根节点,其次就是左节点

while(p) {cout << p ->data; //访问根节点s.push(p); //保存左子节点p = p->left;
}

接着再弹栈,直到获取一个右节点

while(!s.empty()) {p = s.top();s.pop();p = p -> right;
}

接着再重复对右节点进行同样的访问操作,具体过程如下

/*非递归先序遍历*/
void preOrderNoRecur(Tree *root) {if (root == NULL) {return;}stack<TreeNode> s;Tree *p = root;while(!s.empty() || p) {while(p) {cout << p ->data;s.push(p);p = p->left;}while(!s.empty()) {p = s.top();s.pop();p = p -> right;}}cout << endl;
}

中序遍历

中序遍历二叉树是指:先访问左节点,中间访问根节点,最后访问右节点
分治过程如下:

void inorder(Tree *root) {if (root == NULL) {return;}inorder(root -> left);cout << root -> data;inorder(root -> right);
}

中序遍历二叉树的非递归方式和先序类似,支持访问的时机是在先访问第一轮所有的左节点,再获取右节点之前进行根节点的访问,实现过程如下:

/*非递归中序遍历*/
void inorderNoRecur(Tree *root) {if (root == NULL) {return;}stack<TreeNode> s;Tree *p = root;while(!s.empty() || p) {while(p) {s.push(p);p = p ->left;}while(!s.empty()) {p = s.top();cout << p->data;s.pop();p = p->right;}}cout << endl;
}

后序遍历

后序遍历二叉树是指:先访问左节点,再访问右节点,最后访问根节点
分治过程如下:

/*递归后序遍历*/
void lastorder(Tree *root) {if (root == NULL) {return;}lastorder(root -> left);lastorder(root -> right);cout << root -> data;
}

非递归的访问过程和先序/中序遍历有差异,因为后序遍历需要优先访问完左节点、右节点
所以根节点的访问前提是:

  1. 右子节点为空
  2. 右子节点已经访问过

所以实现的过程中需要保存已经访问过的右子节点

void lastorderNoRecur(Tree *root) {if (root == NULL) {return;}stack<TreeNode> s;Tree *p = root;Tree *lastvisit = NULL;//保存已经访问过的右子节点/*先获取到左子节点*/while(p) {s.push(p);p = p ->left;}while(!s.empty()) {p = s.top();s.pop();/*右节点已经为空或者已经访问过,那么认为右节点已经访问完,可以访问根节点了*/if (p -> right == NULL || p ->right == lastvisit) {cout << p->data;lastvisit = p;} else {//否则,将右节点以及右节点的子节点入栈从而继续访问s.push(p);p = p -> right;/*每获取到一个非空右节点,就将该右节点的左节点放入栈中*/while(p) {s.push(p);p = p -> left;}}}cout << endl;
}

获取叶子节点个数

叶子节点的条件就是:左右子树都为空
此时返回值应该为1
分治+归并获取叶子节点的个数

int getLeavesNode(Tree *root) {if (root == NULL) {return 0;} else {if (root -> left == NULL && root ->right == NULL) {return 1;}return getLeavesNode(root -> left) + getLeavesNode(root -> right);}
}

获取树的高度

树的高度为左右子节点的 层数较大的一个数值
实现过程如下:

int heightTree(Tree *root) {int height = 0;if (root == NULL) {return 0;} else {int l_height = heightTree(root -> left);int r_height = heightTree(root -> right);height = l_height > r_height? l_height +1 :r_height+1;}return height;
}

测试代码

#include <iostream>
#include <stack>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>using namespace std;typedef struct tree
{char data;struct tree *left;struct tree *right;
}Tree,*TreeNode;/*创建二叉树*/
void createTree(TreeNode *root) {char val = 0;cin >> val;if (val == '*') {(*root) = NULL;} else {(*root) = (Tree *)malloc(sizeof(tree));if ((*root) == NULL) {cout << "create node failed " << endl;exit(-1);} else {(*root)->data = val;createTree(&(*root)->left);createTree(&(*root)->right);}}
}/*递归先序遍历*/
void preOrder(Tree *root) {if (root == NULL) {return;}cout << root->data;preOrder(root->left);preOrder(root->right);
}/*非递归先序遍历*/
void preOrderNoRecur(Tree *root) {if (root == NULL) {return;}stack<TreeNode> s;Tree *p = root;while(!s.empty() || p) {while(p) {cout << p ->data;s.push(p);p = p->left;}while(!s.empty()) {p = s.top();s.pop();p = p -> right;}}cout << endl;}/*递归中序遍历*/
void inorder(Tree *root) {if (root == NULL) {return;}inorder(root -> left);cout << root -> data;inorder(root -> right);
}/*非递归中序遍历*/
void inorderNoRecur(Tree *root) {if (root == NULL) {return;}stack<TreeNode> s;Tree *p = root;while(!s.empty() || p) {while(p) {s.push(p);p = p ->left;}while(!s.empty()) {p = s.top();cout << p->data;s.pop();p = p->right;}}cout << endl;
}/*递归后序遍历*/
void lastorder(Tree *root) {if (root == NULL) {return;}lastorder(root -> left);lastorder(root -> right);cout << root -> data;
}void lastorderNoRecur(Tree *root) {if (root == NULL) {return;}stack<TreeNode> s;Tree *p = root;Tree *lastvisit = NULL;while(p) {s.push(p);p = p ->left;}while(!s.empty()) {p = s.top();s.pop();/*右节点已经为空或者已经访问过,那么认为右节点已经访问完,可以访问根节点了*/if (p -> right == NULL || p ->right == lastvisit) {cout << p->data;lastvisit = p;} else {//否则,将右节点以及右节点的子节点入栈从而继续访问s.push(p);p = p -> right;while(p) {s.push(p);p = p -> left;}}}cout << endl;
}int getLeavesNode(Tree *root) {if (root == NULL) {return 0;} else {if (root -> left == NULL && root ->right == NULL) {return 1;}return getLeavesNode(root -> left) + getLeavesNode(root -> right);}
}int heightTree(Tree *root) {int height = 0;if (root == NULL) {return 0;} else {int l_height = heightTree(root -> left);int r_height = heightTree(root -> right);height = l_height > r_height? l_height +1 :r_height+1;}return height;
}int main(int argc, char const *argv[])
{/* code */TreeNode root;cout << "construct the tree " << endl;createTree(&root);cout << "previous order recursion " << endl;preOrder(root);cout << "\nprevious order no recursion " << endl;preOrderNoRecur(root);cout << "inorder recursion " << endl;inorder(root);cout << "\ninorder no recursion " << endl;inorderNoRecur(root);cout << "lastorder recursion " << endl;lastorder(root);cout << "\nlastorder no recursion " << endl;lastorderNoRecur(root);cout << "height of the tree is " << heightTree(root) << endl;cout << "num leaves of the tree is " << getLeavesNode(root) << endl;return 0;
}

输出如下:

#输入
construct the tree
ABD***CE**FG***
#输出
previous order recursion
ABDCEFG
previous order no recursion
ABDCEFG
inorder recursion
DBAECGF
inorder no recursion
DBAECGF
lastorder recursion
DBEGFCA
lastorder no recursion
DBEGFCA
height of the tree is 4
num leaves of the tree is 3

二叉树(C++):创建,前中后序遍历(递归+非递归),获取叶子节点个数,获取树的高度相关推荐

  1. 二叉树前中后序遍历的非递归实现以及层次遍历、zig-zag型遍历详解

    前言 二叉树的遍历是一个比较常见的问题,递归实现二叉树的前中后序遍历比较简单,但非递归实现二叉树的前中后序遍历相对有难度.这篇博客将详述如何使用非递归的方式实现二叉树的前中后序遍历,在进行理论描述的同 ...

  2. 二叉树的层序遍历和前中后序遍历代码 迭代/递归

    二叉树的层序遍历和前中后序遍历代码 迭代/递归 只记录代码.思路参考代码随想录:https://github.com/youngyangyang04/leetcode-master/blob/mast ...

  3. LeetCode——树:层次遍历、前中后序遍历

    LeetCode--树:层次遍历.前中后序遍历 目录 层次遍历 二叉树的层平均值 找树左下角的值 前中后序遍历 概述 非递归实现二叉树的前序遍历 非递归实现二叉树的中序遍历 非递归实现二叉树的后序遍历 ...

  4. 二叉树前中后序遍历+刷题【中】【数据结构/初阶/C语言实现】

    文章目录 1. 二叉树基础操作 1.1 二叉树遍历 1.1.1 前序遍历 前序遍历(Pre-Order Traversal) 1.1.2 中序遍历 中序遍历(In-Order Traversal) 1 ...

  5. python实现二叉树非递归前中后序遍历

    python实现二叉树非递归前中后层序遍历 二叉树是数据结构中重要的一部分,本文简单介绍用python实现二叉树的前中后序遍历,包括递归和非递归思路算法. # -*- 二叉树 begin -*- # ...

  6. 二叉树前中后序遍历以及节点计算

    二叉树前中后序遍历以及节点计算 二叉树 分类 二叉链的数据结构 三叉链的数据结构 四种遍历方法 深度优先遍历:前中后序 广度优先遍历:层序遍历 计算 节点个数 叶子节点个数 树的高度 第k层的节点个数 ...

  7. 二叉树的前,中,后序遍历(思路分析) [Java][数据结构]

    二叉树的前,中,后序遍历(思路分析) 前序遍历: 先输出父节点, 再遍历左子树和右子树 中序遍历: 先遍历左子树, 再输出父节点,再遍历右子树 后序遍历: 先遍历左子树,再遍历右子树,最后输出父节点 ...

  8. 二叉树N叉数的前中后序遍历总结,python实现递归法和迭代法

    关于二叉树的前序遍历(preoder).中序遍历(inorder)和后序遍历(postorder),实际上只需要记住:左子节点一定在右子节点的左边(左右),所谓前中后序遍历就是根节点的位置不同,前序是 ...

  9. [Leedcode][JAVA][第94/144/145题][前中后序遍历][递归][迭代][二叉树]

    [问题描述][] 前序遍历 先输出当前结点的数据,再依次遍历输出左结点和右结点 中序遍历 先遍历输出左结点,再输出当前结点的数据,再遍历输出右结点 后续遍历 先遍历输出左结点,再遍历输出右结点,最后输 ...

最新文章

  1. swift3.0最新拨打电话方法
  2. 零基础该如何系统地自学Python编程?五个阶段带你从小白到大佬
  3. shell中几个特殊的符号
  4. python astype(float)_Python astype(np.float)函数使用方法解析
  5. 机器学习(三十五)——Actor-Critic, Integrating Learning and Planning(1)
  6. Android之MVP 模式:简单易懂的介绍方式
  7. java 16进制数组 字符串_byte数组转换成16进制字符串和字符数组的方法
  8. python变量命名规则_Python教程第9篇:牢记Python变量命名5大规则
  9. 常用算法一(分治算法)
  10. Springboot 应用部署建议
  11. hive的hql怎么运行_在Ubuntu上安装Apache Hive并运行HQL查询
  12. cmake使用介绍【转】
  13. 阶乘的传统流程图 c语言,C语言算法与流程图.ppt
  14. MATLAB学习笔记(二)——数据及其运算
  15. 大学生选课抢课如何提高选中概率
  16. 水晶五笔下载地址(非技术)
  17. qt设置背景图片注意事项
  18. 如何在GitHub上创建自己的仓库?
  19. Vss2005安装配置
  20. 2020年最新人工智能算法工程师学习资料大全!!!

热门文章

  1. LINQ 学习路程 -- 查询操作 GroupBy ToLookUp
  2. Auty 2017——WebMonitor接口线上检测平台
  3. Retrofit源码研究
  4. 2.抽取代码(BaseActivity)
  5. poj2965-poj2965-The Pilots Brothers' refrigerator
  6. 【Leetcode】 刷题之路1(python)
  7. usaco shuttle puzzle(dfs剪枝)
  8. video怎么重新加载 vue_vue.js中vue-video-player中的怎么插入多个视频,视频可以同时播放的问题及解决办法...
  9. 基于python的证件照_20行代码教你用python给证件照换底色的方法示例
  10. linux内核和cpu指令集,Linux之父:Intel别浪费时间在AVX512这类指令集、多堆核心才是正道...