二叉树的递归与迭代遍历
概述
1. 二叉树的递归序
而所谓的前中后序则为递归序中数字出现的次序
- 前序(第一次出现):1,2,4,5,3,6,7
- 中序(第二次出现):4,2,5,1,6,3,7
- 后序(第三次出现):4,5,2,6,7,3,1
2. 二叉树的遍历方式
- 深度优先遍历
- 前序遍历(递归法,非递归法)
- 中序遍历(递归法,非递归法)
- 后序遍历(递归法,非递归法)
- 广度优先遍历
- 层次遍历(非递归法)
1.递归遍历
前中后序指的就是中间节点的位置,即
- 前序遍历:中左右
- 中序遍历:左中右
- 后序遍历:左右中
树的节点
struct TreeNode{
int value;
TreeNode* left;
TreeNode* right;
TreeNode(int val): value(val),left(NULL),right(NULL){}
};
1.1 先序遍历
void preOrderRecur(TreeNode* head){
if(head == NULL){/*递归停止条件*/
return ;
}
cout << head->value << " ";
preOrderRecur(head->left);
preOrderRecur(head->right);
}
1.2 中序遍历
void inOrderRecur(TreeNode* head){
if(head == NULL){
return ;
}
inOrderRecur(head->left);
cout << head->value << " ";
inOrderRecur(head->right);
}
1.3 后序遍历
void posOrderRecur(TreeNode* head){
if(head == NULL){
return ;
}
posOrderRecur(head->left);
posOrderRecur(head->right);
cout << head->value << " ";
}
2. 非递归遍历
2.1 先序遍历
实现步骤:
- 步骤1:申请一个栈sta,把头节点压入栈中
- 步骤2:从sta中弹出栈顶节点,记为cur,打印节点cur的值;再将节点cur的右孩子(若不为空)压入栈中,最后将节点cur的左孩子(若不为空)压入栈中。
- 步骤3:不断重复步骤2,直到栈为空,则结束。
void preOrderUnRecur(TreeNode* head){
cout << "pre-order-UnRecur: " << endl;
if(head == NULL){
return ;
}
stack<TreeNode*> sta;
sta.push(head);
while(!sta.empty()){
TreeNode* cur = sta.top();/*每次弹出都会更新*/
cout << cur->value << " ";
sta.pop();
if(cur->right != NULL) sta.push(cur->right);
if(cur->left != NULL) sta.push(cur->left);
}
cout << endl;
}
2.2 中序遍历
实现步骤:
- 步骤1:申请一个栈sta,初始时,令cur = head;
- 步骤2:先把cur节点压入栈中,对cur节点为头节点的整颗子树来说,依次把左边界压入栈中,即不停的令cur = cur->left;然后重复步骤2;
- 步骤3:不断重复步骤2,直到cur为空,此时从栈中弹出一个节点,记为node,打印node的值,并让cur = cur->right;然后继续重复步骤2.
- 步骤4:栈为空且cur为空时,则停止
void inOrderUnRecur(TreeNode* head){
cout << "In-order-UnRecur:" << endl;
if(head != NULL){
stack<TreeNode*> sta;
TreeNode* cur = head;
while(!sta.empty() || cur != NULL){
if(cur != NULL){
sta.push(cur);
cur = cur->left;
}else{
cur = sta.top();
cout << cur->value << " ";
sta.pop();
cur = cur->right;
}
}
}
cout << endl;
}
2.3 后序遍历
实现步骤:
- 步骤1:申请一个栈s1,然后把头节点压入s1;
- 步骤2:从sta中弹出栈顶节点,记为cur,打印节点cur的值;再将节点cur的左孩子(若不为空)压入栈中,最后将节点cur的右孩子(若不为空)压入栈中【此过程与前序相反】。在整个过程中,把s1弹出的的节点放入另一个栈s2中;
- 不断重复步骤2,直到s1为空,过程停止
- 从s2中依次弹出节点并打印。【s2就相当于一个反转的过程,s1弹出节点的顺序为中右左,经s2打印出来为左右中,即为后序】
void posOrderUnRecur(TreeNode* head){
cout << "pos-order-UnRecur:" << endl;
if(head != NULL){
stack<TreeNode*> s1;
stack<TreeNode*> s2;
s1.push(head);
TreeNode* cur = NULL;
while(!s1.empty()){
cur = s1.top();
s2.push(cur);
s1.pop();
if(cur->left != NULL) s1.push(cur->left);
if(cur->right != NULL) s1.push(cur->right);
}
while(!s2.empty()){
cout << s2.top()->value << " ";
s2.pop();
}
}
cout << endl;
}
3. 测试
#include <iostream>
#include <stack>
using namespace std;
/*树的节点*/
struct TreeNode{
int value;
TreeNode* left;
TreeNode* right;
TreeNode(int val): value(val),left(NULL),right(NULL){}
};
/*创建一棵树*/
TreeNode* createTree(){
TreeNode* head = new TreeNode(1);
head->left = new TreeNode(2);
head->right = new TreeNode(3);
head->left->left = new TreeNode(4);
head->left->right = new TreeNode(5);
head->right->left = new TreeNode(6);
head->right->right = new TreeNode(7);
return head;
}
int main(){
TreeNode* head = createTree();
cout << "pre-order-recur" << endl;
preOrderRecur(head);
cout << endl;
preOrderUnRecur(head);
cout << "in-order-recur:" << endl;
inOrderRecur(head);
cout << endl;
inOrderUnRecur(head);
cout << "pos-order-recur:" << endl;
posOrderRecur(head);
cout << endl;
posOrderUnRecur(head);
return 0;
}