2019年9月11日09:13:41
二叉树的遍历向来是 二叉树学习和应用的重中之重,虽然树结构 使用递归会使得我们的代码更加简洁,但是在这里 我也把非递归版本代码也进行详解。而二叉树 作为DSA中极为重要的一种数据结构,二叉树的基础学习是给后面学习 更加高级的数据结构做铺垫的。话不多说,先看一下 二叉树的遍历吧。
二叉树的遍历
基本概念
遍历:从这棵树的根节点出发,按照某种 次序 逐个依次访问树中的每个节点,直到所有节点都被 有且只有一次被访问到为止。
次序:树的一对多的关系,也就决定了 不同于之前线性结构的比较简单的遍历次序(从头到尾、从尾到头、循环、双向等)。正如这种一对多的结构,决定了 树不存在所谓的 唯一前驱和后继的关系,那么在成功遍历一个节点之后 遍历哪个节点是有多个选择的。正是这里不同的选择也确定了不同的遍历次序,因此树就有了这几种遍历方式。
访问:上面说的访问的意思就是:根据我们的需要所进行的动作。最常见的访问其值val,或者进行一些其他的节点操作等。
二叉树的遍历方式
二叉树的遍历方式是有很多种的,但是通常我们规定为从左到右的遍历方式(当然从右到左也是可以的,只是可能不太符合人们的习惯),遍历主要分为以下四种:
- 先序遍历
- 中序遍历
- 后序遍历
- 层序遍历
先序遍历
其定义:若二叉树为空,则空操作返回;不为空则先访问根结点,然后先序遍历左子树,再先序遍历右子树。遍历过程如下图所示:
因此上面这棵二叉树的 先序遍历,次序为:ABDGHCEIF
遍历步骤如下:
- 二叉树不空,访问根节点,即A
- A的左子树不空,先序遍历A的左子树。左子树的根节点为B,访问 即:AB
- B的左子树不空,先序遍历B的左子树。左子树的根节点为D,访问 即:ABD
- D的左子树不空,先序遍历D的左子树。左子树的根节点为G,访问 即:ABDG
- G的左子树为空 返还上一层
- G的右子树为空 返还上一层
- D的右子树不空,先序遍历D的右子树。右子树的根节点为H,访问 即:ABDGH
- H的左子树为空 返还上一层
- H的右子树为空 返还上一层
- B的右子树为空 返还上一层
- A的右子树不空,先序遍历A的右子树。右子树的根节点为C,访问 即:ABDGHC
- C的左子树不空,先序遍历C的左子树。左子树的根节点为E,访问 即:ABDGHCE
- E的左子树为空 返还上一层
- E的右子树不空,先序遍历E的右子树。右子树的根节点为I,访问 即:ABDGHCEI
- I的左子树为空 返还上一层
- I的右子树为空 返还上一层
- C的右子树不空,先序遍历C的右子树。右子树的根节点为F,访问 即:ABDGHCEIF
- F的左子树为空 返还上一层
- F的右子树为空 返还上一层
代码如下:
1.1 先序遍历的递归版本如下:
/**
* 先序遍历的递归实现,直接根据定义,首先先访问根节点,
* 然后先序遍历左子树,接着先序遍历右子树。
* 上述的每个先序遍历就是一个递归的过程。
*/
class TreeNode
{
public:
TreeNode(char C):val(C),left(nullptr),right(nullptr){}
//先序遍历 递归实现
static void preOrder_Operator(TreeNode* this_root, vector<char>& vec)
{
if (this_root != nullptr)
{
vec.push_back(this_root->val);
preOrder_Operator(this_root->left, vec);
preOrder_Operator(this_root->right, vec);
}
}
//先序遍历 把顺序保存在一个数组中 递归实现
vector<char> preOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
preOrder_Operator(root, myvec);
return myvec;
}
char val;
TreeNode* left;
TreeNode* right;
};
测试如下:
代码如下:
1.2 先序遍历的非递归版本如下:
/*
* 先序遍历的非递归实现,需要借助栈这个数据结构,由于前先遍历是
* 先访问根节点,然后前序遍历左子树,接着前序遍历右子树。
* 那么非递归实现的话,先压入根节点,然后打印栈顶元素,但是由于
* 出栈和入栈的顺序是相反的,因此我们接着需要先压入右孩子,再压入左孩子
* 然后打印栈顶元素,继续压入左孩子的右孩子,左孩子的左孩子···
* 上述便是迭代循环的过程。
*/
//先序遍历 把顺序保存在一个数组中 非递归实现
vector<char> preOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
stack<TreeNode*>mystack;
mystack.push(root);
while (!mystack.empty())
{
TreeNode* top_node = mystack.top();
myvec.push_back(top_node->val);
mystack.pop();
//出栈和入栈的顺序是相反的
if (top_node->right != nullptr)
{
mystack.push(top_node->right);
}
if (top_node->left != nullptr)
{
mystack.push(top_node->left);
}
}
return myvec;
}
中序遍历
其定义:若二叉树为空,则空操作返回;不为空则从根结点开始(注:并不是先访问根结点),中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树。遍历过程如下图所示:
因此上面这棵二叉树的 中序遍历,次序为:GDHBAEICF
遍历步骤如下:
- 二叉树不空,根节点A存在左子树,则中序遍历其左子树。左子树根为B
- B存在左子树,则中序遍历其左子树。左子树根为D
- D存在左子树,则中序遍历其左子树。左子树根为G
- G的左子树为空,返还上一层
- 访问节点G,即G
- G的右子树为空,返还上一层
- 访问节点D,即GD
- D存在右子树,则中序遍历其右子树。右子树根为H
- H的左子树为空,返还上一层
- 访问节点H,即GDH
- H的右子树为空,返还上一层
- 访问节点B,即GDHB
- B的右子树为空,返还上一层
- 访问节点A,即GDHBA
- A存在右子树,则中序遍历其右子树。右子树根为C
- C存在左子树,则中序遍历其左子树。左子树根为E
- E的左子树为空,返还上一层
- 访问节点E,即GDHBAE
- E存在右子树,则中序遍历其右子树。右子树根为I
- I的左子树为空,返还上一层
- 访问节点I,即GDHBAEI
- I的右子树为空,返还上一层
- 访问节点C,即GDHBAEIC
- C存在右子树,则中序遍历其右子树。右子树根为F
- F的左子树为空,返还上一层
- 访问节点F,即GDHBAEICF
- F的右子树为空,返还上一层
代码如下:
2.1 中序遍历的递归版本如下:
/*
* 中序遍历的递归实现,根据定义,首先中序遍历左子树,
* 再打印根节点,然后再中序遍历右子树。
* 上述的每个中序遍历就是一个递归的过程。
*/
//中序遍历 递归实现
static void inOrder_Operator(TreeNode* this_root, vector<char>& vec)
{
if (this_root != nullptr)
{
inOrder_Operator(this_root->left, vec);
vec.push_back(this_root->val);
inOrder_Operator(this_root->right, vec);
}
}
//中序遍历 把顺序保存在一个数组中 递归实现
vector<char>inOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
inOrder_Operator(root, myvec);
return myvec;
}
测试如下:
代码如下:
2.2 中序遍历的非递归版本如下:
/*
* 中序遍历的非递归实现,首先应该一直向左遍历,将结点压栈,
* 直到结点为空,然后我们打印该节点值,并将其出栈,并继续遍历该节点的右子树
* 继续上述过程。
*/
//中序遍历 把顺序保存在一个数组中 非递归实现
vector<char>inOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
stack<TreeNode*>mystack;
TreeNode* top_node = root;
while (!mystack.empty() || top_node!=nullptr)
{
if (top_node!= nullptr)//左孩子存在 一直走
{
mystack.push(top_node);
top_node = top_node->left;
}
else
{
top_node = mystack.top();
myvec.push_back(top_node->val);
mystack.pop();
top_node = top_node->right;
}
}
return myvec;
}
后序遍历
其定义:若二叉树为空,则空操作返回;不为空则从左到右先叶子后结点的方式遍历访问左右子树,最后是访问根结点。遍历过程如下图所示:
因此上面这棵二叉树的 后序遍历,次序为:GHDBIEFCA
遍历步骤如下:
- 二叉树不空,根节点A存在左子树,则后序遍历其左子树。左子树根为B
- B存在左子树,则后序遍历其左子树。左子树根为D
- D存在左子树,则后序遍历其左子树。左子树根为G
- G的左子树为空,返还上一层
- G的右子树为空,返还上一层
- 访问节点G,即G
- D存在右子树,则后序遍历其左子树。右子树根为H
- H的左子树为空,返还上一层
- H的右子树为空,返还上一层
- 访问节点H,即GH
- 访问节点D,即GHD
- B的右子树为空,返还上一层
- 访问节点B,即GHDB
- A存在右子树,则后序遍历其右子树。右子树根为C
- C存在左子树,则后序遍历其左子树。左子树根为E
- E的左子树为空,返还上一层
- E存在右子树,则后序遍历其右子树。右子树根为I
- I的左子树为空,返还上一层
- I的右子树为空,返还上一层
- 访问节点I,即GHDBI
- 访问节点E,即GHDBIE
- C存在右子树,则后序遍历其右子树。右子树根为F
- F的左子树为空,返还上一层
- F的右子树为空,返还上一层
- 访问节点F,即GHDBIEF
- 访问节点C,即GHDBIEFC
- 访问节点A,即GHDBIEFCA
代码如下:
3.1 后序遍历的递归版本如下:
/*
* 后序遍历的递归实现,只需先后序遍历左子树,再后序遍历右子树
* 最后打印根节点值即可。
* 上述的每个后序遍历就是一个递归的过程。
*/
//后序遍历 递归实现
static void lastOrder_Operator(TreeNode* this_root, vector<char>& vec)
{
if (this_root != nullptr)
{
lastOrder_Operator(this_root->left, vec);
lastOrder_Operator(this_root->right, vec);
vec.push_back(this_root->val);
}
}
//后序遍历 把顺序保存在一个数组中 递归实现
vector<char>lastOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
lastOrder_Operator(root, myvec);
return myvec;
}
测试如下:
代码如下:
3.2 后序遍历的非递归版本如下:
/*
* 后序遍历的非递归实现,由于其根节点最后打印,因此这里需要借助两个栈来完成,
* 因为需要借助一个辅助栈来保存其父节点,而另一个栈则用来保存我们的结果集。
* 注意压栈顺序,本来应该先压右孩子,再压左孩子。但是使用另一个结果栈
* 来存储结果集,辅助栈中的元素最终是出栈并压入结果栈的,因此,程序中
* 应该先压入左孩子,再压入右孩子。
* 然后每次循环将栈顶元素出栈并压入结果栈中。
* 最后,结果栈中所存储的就是我们所需的后序遍历结果集。打印出栈中所有的
* 元素即可
*/
//后序遍历 把顺序保存在一个数组中 非递归实现
vector<char>lastOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
stack<TreeNode*>mystack;//这个作为工作栈
mystack.push(root);
while (!mystack.empty())
{
TreeNode* top_node = mystack.top();
myvec.push_back(top_node->val); //这个入结果数组顺序是反向的
mystack.pop();
if (top_node->left != nullptr)//因为入栈和出栈顺序相反
mystack.push(top_node->left);
if (top_node->right != nullptr)
mystack.push(top_node->right);
}
//把最终的顺序一反序即可 不用再用临时结果栈了
reverse(myvec.begin(), myvec.end());
return myvec;
}
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
递归版本的代码如下:
/**══════════════════════════════════╗
*作 者:songbaobao ║
*CSND地址:https://blog.csdn.net/weixin_43949535 ║
***GitHub:https://github.com/TsinghuaLucky912/My_own_C-_study_and_blog║
*═══════════════════════════════════╣
*创建时间:2019年9月11日12:07:06
*功能描述:
*
*
*═══════════════════════════════════╣
*结束时间: 2019年9月11日14:17:18
*═══════════════════════════════════╝
// .-~~~~~~~~~-._ _.-~~~~~~~~~-.
// __.' ~. .~ `.__
// .'// 西南\./联大 \\`.
// .'// | \\`.
// .'// .-~"""""""~~~~-._ | _,-~~~~"""""""~-. \\`.
// .'//.-" `-. | .-' "-.\\`.
// .'//______.============-.. \ | / ..-============.______\\`.
//.'______________________________\|/______________________________`.
*/
#include <iostream>
#include <vector>
using namespace std;
class TreeNode
{
public:
TreeNode(char C):val(C),left(nullptr),right(nullptr){}
static void preOrder_Operator(TreeNode* this_root, vector<char>& vec)//前序遍历 递归实现
{
if (this_root != nullptr)
{
vec.push_back(this_root->val);
preOrder_Operator(this_root->left, vec);
preOrder_Operator(this_root->right, vec);
}
}
//前序遍历 把顺序保存在一个数组中 递归实现
vector<char> preOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
preOrder_Operator(root, myvec);
return myvec;
}
//中序遍历 递归实现
static void inOrder_Operator(TreeNode* this_root, vector<char>& vec)
{
if (this_root != nullptr)
{
inOrder_Operator(this_root->left, vec);
vec.push_back(this_root->val);
inOrder_Operator(this_root->right, vec);
}
}
//中序遍历 把顺序保存在一个数组中 递归实现
vector<char>inOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
inOrder_Operator(root, myvec);
return myvec;
}
//后序遍历 递归实现
static void lastOrder_Operator(TreeNode* this_root, vector<char>& vec)
{
if (this_root != nullptr)
{
lastOrder_Operator(this_root->left, vec);
lastOrder_Operator(this_root->right, vec);
vec.push_back(this_root->val);
}
}
//后序遍历 把顺序保存在一个数组中 递归实现
vector<char>lastOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
lastOrder_Operator(root, myvec);
return myvec;
}
char val;
TreeNode* left;
TreeNode* right;
};
int main()
{
TreeNode tree(0);
char Carray[] = { 'A','B','C','D','E','F','G','H','I' };
TreeNode* root = nullptr;
TreeNode* pArray[9] = { nullptr };
int i = 0;
for (char val : Carray)
{
pArray[i++] = new TreeNode(val);
}
pArray[0]->left = pArray[1]; pArray[0]->right = pArray[2];
pArray[1]->left = pArray[3];
pArray[2]->left = pArray[4]; pArray[2]->right = pArray[5];
pArray[3]->left = pArray[6]; pArray[3]->right = pArray[7];
pArray[4]->right = pArray[8];
root = pArray[0];
vector<char>myvec_pre = tree.preOrder(root);
cout << "二叉树的先序遍历序列递归版本:";
for (char val : myvec_pre)
{
cout << val << " ";
}
cout << endl;
vector<char>myvec_in = tree.inOrder(root);
cout << "二叉树的中序遍历序列递归版本:";
for (char val : myvec_in)
{
cout << val << " ";
}
cout << endl;
vector<char>myvec_last = tree.lastOrder(root);
cout << "二叉树的后序遍历序列递归版本:";
for (char val : myvec_last)
{
cout << val << " ";
}
cout << endl;
return 0;
}
/**
*备用注释:
*
*
*
*/
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
非递归版本的代码如下:
/**══════════════════════════════════╗
*作 者:songbaobao ║
*CSND地址:https://blog.csdn.net/weixin_43949535 ║
***GitHub:https://github.com/TsinghuaLucky912/My_own_C-_study_and_blog║
*═══════════════════════════════════╣
*创建时间:2019年9月11日14:20:09
*功能描述:
*
*
*═══════════════════════════════════╣
*结束时间: 2019年9月11日15:21:57
*═══════════════════════════════════╝
// .-~~~~~~~~~-._ _.-~~~~~~~~~-.
// __.' ~. .~ `.__
// .'// 西南\./联大 \\`.
// .'// | \\`.
// .'// .-~"""""""~~~~-._ | _,-~~~~"""""""~-. \\`.
// .'//.-" `-. | .-' "-.\\`.
// .'//______.============-.. \ | / ..-============.______\\`.
//.'______________________________\|/______________________________`.
*/
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
class TreeNode
{
public:
TreeNode(char C) :val(C), left(nullptr), right(nullptr) {}
//前序遍历 把顺序保存在一个数组中 非递归实现
vector<char> preOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
stack<TreeNode*>mystack;
mystack.push(root);
while (!mystack.empty())
{
TreeNode* top_node = mystack.top();
myvec.push_back(top_node->val);
mystack.pop();
//出栈和入栈的顺序是相反的
if (top_node->right != nullptr)
{
mystack.push(top_node->right);
}
if (top_node->left != nullptr)
{
mystack.push(top_node->left);
}
}
return myvec;
}
//中序遍历 把顺序保存在一个数组中 非递归实现
vector<char>inOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
stack<TreeNode*>mystack;
TreeNode* top_node = root;
while (!mystack.empty() || top_node!=nullptr)
{
if (top_node!= nullptr)//左孩子存在 一直走
{
mystack.push(top_node);
top_node = top_node->left;
}
else
{
top_node = mystack.top();
myvec.push_back(top_node->val);
mystack.pop();
top_node = top_node->right;
}
}
return myvec;
}
//后序遍历 把顺序保存在一个数组中 非递归实现
vector<char>lastOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
stack<TreeNode*>mystack;//这个作为工作栈
mystack.push(root);
while (!mystack.empty())
{
TreeNode* top_node = mystack.top();
myvec.push_back(top_node->val); //这个入结果数组顺序是反向的
mystack.pop();
if (top_node->left != nullptr)
mystack.push(top_node->left);
if (top_node->right != nullptr)//因为入栈和出栈顺序相反
mystack.push(top_node->right);
}
//把最终的顺序一反序即可 不用再用临时结果栈了
reverse(myvec.begin(), myvec.end());
return myvec;
}
char val;
TreeNode* left;
TreeNode* right;
};
int main()
{
TreeNode tree(0);
char Carray[] = { 'A','B','C','D','E','F','G','H','I' };
TreeNode* root = nullptr;
TreeNode* pArray[9] = { nullptr };
int i = 0;
for (char val : Carray)
{
pArray[i++] = new TreeNode(val);
}
pArray[0]->left = pArray[1]; pArray[0]->right = pArray[2];
pArray[1]->left = pArray[3];
pArray[2]->left = pArray[4]; pArray[2]->right = pArray[5];
pArray[3]->left = pArray[6]; pArray[3]->right = pArray[7];
pArray[4]->right = pArray[8];
root = pArray[0];
vector<char>myvec_pre = tree.preOrder(root);
cout << "二叉树的先序遍历序列非递归版本:";
for (char val : myvec_pre)
{
cout << val << " ";
}
cout << endl;
vector<char>myvec_in = tree.inOrder(root);
cout << "二叉树的中序遍历序列非递归版本:";
for (char val : myvec_in)
{
cout << val << " ";
}
cout << endl;
vector<char>myvec_last = tree.lastOrder(root);
cout << "二叉树的后序遍历序列非递归版本:";
for (char val : myvec_last)
{
cout << val << " ";
}
cout << endl;
return 0;
}
/**
*备用注释:
*
*
*
*/
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
层次遍历
其定义:若二叉树为空,则空操作返回;不为空则从树的第一层,也就是根结点开始访问,从上而下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。
因此上面这棵二叉树的 层次遍历,次序为:ABCDEFGHI
遍历步骤如下:
- 二叉树不空,访问第1层 A入队
- (队头A出队)访问 即A。A的左孩子存在 右孩子存在 (B、C入队)
- (队头B出队)访问 即AB。B的左孩子存在 右孩子不存在 (D入队)
- (队头C出队)访问 即ABC。C的左孩子存在 右孩子存在 (E、F入队)
- (队头D出队)访问 即ABCD。D的左孩子存在 右孩子存在 (G、H入队)
- (队头E出队)访问 即ABCDE。E的左孩子不存在 右孩子存在 (I入队)
- (队头F出队)访问 即ABCDEF。F的左孩子不存在 右孩子不存在
- (队头G出队)访问 即ABCDEFG。G的左孩子不存在 右孩子不存在
- (队头H出队)访问 即ABCDEFGH。H的左孩子不存在 右孩子不存在
- (队头I出队)访问 即ABCDEFGHI。I的左孩子不存在 右孩子不存在
代码如下:
4.1 层次遍历的递归版本如下:
/*
* 层序遍历不同于上面的前序、中序、后序遍历的DFS,而它是一种典型的BFS
* 那么对于层序遍历的递归实现,就必须要获取到该树的层数,才能对递归进行一个有效的控制
* 整体思路就是:向递归函数levelOrder_Operator ,循环传入层数(0-n)
* 在递归函数中,层数为零,我们直接打印其值即可,若层数不为零,我们就递归
* 地继续向下遍历。
*
* 那么如何向下继续遍历?我们每次递归遍历就将层数减一即可,那么比如我们遍历第3层
* 元素,那么传入的参数为3,我们递归调用函数,不断的将参数减一,当减到0时便是
* 已经遍历到第三层了,参数减到0,递归结束条件满足,我们直接打印其值即可。
*/
//计算一棵二叉树的层次
int getLevel(TreeNode* root)
{
if (root == nullptr)
return 0;
else
{
return 1 + max(getLevel(root->left), getLevel(root->right));
}
}
void levelOrder_Operator(TreeNode* this_node, int level, vector<char>& myvec)
{
if (this_node == nullptr)
return;
if (level == 0)//达到该层
{
myvec.push_back(this_node->val);
}
else
{
//既然没有达到该层,则指针向下走
levelOrder_Operator(this_node->left, level - 1, myvec);
levelOrder_Operator(this_node->right, level - 1, myvec);
}
}
//层序遍历 把顺序保存在一个数组中 递归实现
vector<char>levelOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
int level = getLevel(root);
for (int i = 0; i < level; ++i)
{
levelOrder_Operator(root, i, myvec);
}
return myvec;
}
测试如下:
代码如下:
4.2 层次遍历的非递归版本如下:
/*
* 层序遍历的非递归实现,正常思路我们先遍历左子树,再遍历右子树,由于是
* 层序遍历,从上到下,从左到右,那么从左到右刚好满足队列的性质,先入先出
* 那么我们需要借助一个队列来保存我们遍历到的元素。
* 第一步:压入根节点。
* 第二步:每次遍历我们拿到队列的首元素,然后遍历其左孩子,并入队;然后遍历其右孩子
* 并入队
* 第三步:然后将队首元素打印并出队,继续迭代
* 直到队列为空。
*/
//层序遍历 把顺序保存在一个数组中 非递归实现
vector<char>nonlevelOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
queue<TreeNode*>myque;
myque.push(root);
while (!myque.empty())
{
TreeNode* head_node = myque.front();
myvec.push_back(head_node->val);
myque.pop();
if (head_node->left != nullptr)
myque.push(head_node->left);
if (head_node->right != nullptr)
myque.push(head_node->right);
}
return myvec;
}
测试如下:
层序遍历的全部源代码如下:
/**══════════════════════════════════╗
*作 者:songbaobao ║
*CSND地址:https://blog.csdn.net/weixin_43949535 ║
***GitHub:https://github.com/TsinghuaLucky912/My_own_C-_study_and_blog║
*═══════════════════════════════════╣
*创建时间:2019年9月11日15:29:39
*功能描述:
*
*
*═══════════════════════════════════╣
*结束时间: 2019年9月11日16:21:58
*═══════════════════════════════════╝
// .-~~~~~~~~~-._ _.-~~~~~~~~~-.
// __.' ~. .~ `.__
// .'// 西南\./联大 \\`.
// .'// | \\`.
// .'// .-~"""""""~~~~-._ | _,-~~~~"""""""~-. \\`.
// .'//.-" `-. | .-' "-.\\`.
// .'//______.============-.. \ | / ..-============.______\\`.
//.'______________________________\|/______________________________`.
*/
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
class TreeNode
{
public:
TreeNode(char C) :val(C), left(nullptr), right(nullptr) {}
//层序遍历 把顺序保存在一个数组中 非递归实现
vector<char>nonlevelOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
queue<TreeNode*>myque;
myque.push(root);
while (!myque.empty())
{
TreeNode* head_node = myque.front();
myvec.push_back(head_node->val);
myque.pop();
if (head_node->left != nullptr)
myque.push(head_node->left);
if (head_node->right != nullptr)
myque.push(head_node->right);
}
return myvec;
}
//计算一棵二叉树的层次
int getLevel(TreeNode* root)
{
if (root == nullptr)
return 0;
else
{
return 1 + max(getLevel(root->left), getLevel(root->right));
}
}
void levelOrder_Operator(TreeNode* this_node, int level, vector<char>& myvec)
{
if (this_node == nullptr)
return;
if (level == 0)//达到该层
{
myvec.push_back(this_node->val);
}
else
{
//既然没有达到该层,则指针向下走
levelOrder_Operator(this_node->left, level - 1, myvec);
levelOrder_Operator(this_node->right, level - 1, myvec);
}
}
//层序遍历 把顺序保存在一个数组中 递归实现
vector<char>levelOrder(TreeNode* root)
{
vector<char>myvec;
if (root == nullptr)
return myvec;
int level = getLevel(root);
for (int i = 0; i < level; ++i)
{
levelOrder_Operator(root, i, myvec);
}
return myvec;
}
char val;
TreeNode* left;
TreeNode* right;
};
int main()
{
TreeNode tree(0);
char Carray[] = { 'A','B','C','D','E','F','G','H','I' };
TreeNode* root = nullptr;
TreeNode* pArray[9] = { nullptr };
int i = 0;
for (char val : Carray)
{
pArray[i++] = new TreeNode(val);
}
pArray[0]->left = pArray[1]; pArray[0]->right = pArray[2];
pArray[1]->left = pArray[3];
pArray[2]->left = pArray[4]; pArray[2]->right = pArray[5];
pArray[3]->left = pArray[6]; pArray[3]->right = pArray[7];
pArray[4]->right = pArray[8];
root = pArray[0];
vector<char>myvec_pre = tree.nonlevelOrder(root);
cout << "二叉树的层次遍历序列非递归版本:";
for (char val : myvec_pre)
{
cout << val << " ";
}
cout << endl;
vector<char>myvec_in = tree.levelOrder(root);
cout << "二叉树的层次遍历序列的递归版本:";
for (char val : myvec_in)
{
cout << val << " ";
}
cout << endl;
return 0;
}
/**
*备用注释:
*
*
*
*/