二叉树的遍历有前序遍历(遍历顺序:根->左->右),中序遍历(遍历顺序:左->根->右),后序遍历(遍历顺序:左->右->根),可以看出,这里的“前/中/后”是对根的位置而言的。哦对,还有一种遍历方法叫做层序遍历,下面就来C++实现下。(代码中除了各种遍历方法,还有求树深,树的镜像二叉树的镜像(剑指offer),以及根据两个遍历序列重构二叉树的实现)
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
//定义树的节点
typedef struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
} TreeNode;
void FrontPrint(TreeNode* root){
if(root == nullptr){
return;
}
//根
printf("%d ", root->val);
//左
FrontPrint(root->left);
//右
FrontPrint(root->right);
}
void FrontPrintByStack(TreeNode* root){
//前序遍历的非递归实现,借助stack
stack<TreeNode*> s;
TreeNode* cur = root;
while (cur!= nullptr || !s.empty()){
//把左子树压栈,直至无左子树
while (cur != nullptr){
printf("%d ", cur->val);//根
s.push(cur);
cur = cur->left;
}
//访问右子树
cur = s.top()->right;
s.pop();//出栈
}
}
void MidPrint(TreeNode* root){
//左根右
if(root== nullptr) return;
//左
MidPrint(root->left);
//根
printf("%d ", root->val);
//右
MidPrint(root->right);
}
void MidPrintByStack(TreeNode* root){
//左根右
stack<TreeNode*> s;
TreeNode* cur = root;
while (cur != nullptr || !s.empty()){
while(cur != nullptr){
s.push(cur);
cur = cur->left;
}
cur = s.top();
s.pop();
printf("%d ", cur->val);
cur = cur->right;
}
}
void BackPrint(TreeNode* root){
if(root== nullptr) return;
//左
BackPrint(root->left);//递归调用其实是一次压栈
//右
BackPrint(root->right);
//根
printf("%d ", root->val);
}
void BackPrintByStack(TreeNode* root){
//左右根 参考https://blog.youkuaiyun.com/monster_ii/article/details/82115772
stack<TreeNode*> s;
TreeNode* cur = root;
TreeNode* top, *last= nullptr;//last可以表示是从左子树返回根节点还是从右子树返回根节点
while (cur != nullptr || !s.empty()){
while(cur != nullptr){
s.push(cur);
cur = cur->left;
}
top = s.top();//栈中保存的元素是它的右子树和自身都没有被遍历到的节点
if (top->right == nullptr || top->right == last){
s.pop();
printf("%d ", top->val);
last = top;
}
else {
cur = top->right;
}
}
}
void LevelPrintbByQueue(TreeNode* root){
//层序遍历二叉树并输出 用队列实现
queue<TreeNode*> q;
if(root != nullptr){
q.push(root);
}
while(!q.empty()){
TreeNode *tmp = q.front(); //队首
printf("%d ", tmp->val);
if(tmp->left != nullptr){
q.push(tmp->left);
}
if(tmp->right != nullptr){
q.push(tmp->right);
}
q.pop();
}
printf("\n");
}
void LevelPrintbByArray(TreeNode* root){
//层序遍历二叉树并输出 用数组实现 https://blog.youkuaiyun.com/m0_37925202/article/details/80796010
TreeNode* a[100];
int in=0, out=0;//in表示进入数组的元素数,out表示出数组的元素数,[out,in]区间就是模拟的当前的队列
if(root != nullptr){
a[in++] = root;
}
while(in > out){
printf("%d ",a[out]->val);
if(a[out]->left != nullptr){
a[in++] = a[out]->left;
}
if(a[out]->right != nullptr){
a[in++] = a[out]->right;
}
out++;
}
}
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
//根据前序遍历pre和中序遍历vin重建二叉树
//递归方法
//停止条件
if(pre.size() == 0){
return nullptr;
}
//解题步骤
vector<int> lpre,lvin,rpre,rvin;
//确定root
TreeNode* root = new TreeNode(pre[0]);
//在中序中找到root的位置,以及左右子树
int loc = 0;//root在中序遍历的位置
int flag = 0;
//对于中序遍历数组,下标0到loc,其中下标0到loc-1是左子树,loc是根节点
for(int i=0;i<vin.size();i++){
if(vin[i] == root->val){
loc = i;
flag = 1;
}
else{
if(flag == 0){
lvin.push_back(vin[i]);
}
else{
rvin.push_back(vin[i]);
}
}
}
//对于前序遍历数组,下标0到loc,其中0是根节点,1-loc是左子树
for(int i = 1;i < pre.size();i++){
if(i <= loc){
lpre.push_back(pre[i]);
}
else
rpre.push_back(pre[i]);
}
//得到左右子树
root->left = reConstructBinaryTree(lpre,lvin);
root->right = reConstructBinaryTree(rpre,rvin);
//返回以root为根节点的树
return root;
}
void Mirror(TreeNode *pRoot) {
//树的镜像
queue<TreeNode *>q;//使用队列对树进行层序遍历
if(pRoot == nullptr){
return;
}
else{
q.push(pRoot);
}
while(!q.empty()){
TreeNode* f = q.front();
if(f->left!=nullptr || f->right!=nullptr){
//只要不是叶节点,就交换左子树和右子树
TreeNode* tmp = f->left;
f->left = f->right;
f->right = tmp;
tmp = nullptr;
}
if(f->left != nullptr)
q.push(f->left);
if(f->right != nullptr)
q.push(f->right);
q.pop();
}
}
int maxn = 0;
int len = 0;
//树深=树中最长的路径长度
int TreeDepth(TreeNode* pRoot)
{
if(pRoot==nullptr){
//该条路径搜索结束
if(len>maxn){
maxn=len;
}
}
else{
len++;//当前节点在路径上
TreeDepth(pRoot->left);//虽然有return但不一定要用变量去接受这个返回值
TreeDepth(pRoot->right);
len--;//返回上一个节点,即当前节点不在路径上
}
return maxn;
}
int main(){
vector<int> pre = {1,2,3,4,5,6,7};//前序遍历
vector<int> vin = {3,2,4,1,6,5,7};//中序遍历
TreeNode* ans = reConstructBinaryTree(pre,vin);
LevelPrintbByQueue(ans);
LevelPrintbByArray(ans);
printf("\n");
FrontPrint(ans);
printf("\n");
FrontPrintByStack(ans);
printf("\n");
MidPrint(ans);
printf("\n");
MidPrintByStack(ans);
printf("\n");
BackPrint(ans);
printf("\n");
BackPrintByStack(ans);
printf("\n");
printf("depth=%d\n", TreeDepth(ans));
Mirror(ans);
LevelPrintbByQueue(ans);
}