二叉树前根序、中根序、后根序遍历分析
借鉴大神博客
https://blog.csdn.net/prince_jun/article/details/7699024
1数组表示二叉树
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int tree[1<<20];//用位运算,1<<20相当于2^20;
int N;
int cur;
void print_01(int index)//调用递归输出,前序遍历
{
if(cur>N)
return ;
if(tree[index]==0)
return ;
printf("%d ",tree[index]);
cur++;
print_01(index*2);//判断左子树的语句在前,递归时优先判断是否存在符合条件的左子树;
print_01(index*2+1);
}
void print_02(int index)//中序遍历
{
if(cur>N)
return ;
if(tree[index]==0)
return ;
print_02(index*2);
printf("%d ",tree[index]);
cur++;
print_02(index*2+1);
}
void print_03(int index)//后序遍历
{
if(cur>N)
return ;
if(tree[index]==0)
return ;
print_03(index*2);
print_03(index*2+1);
printf("%d ",tree[index]);
cur++;
}
int main()
{
while(cin>>N)
{
int node[N+1];
memset(tree,0,sizeof(tree));
for(int i=1;i<=N;i++)
cin>>node[i];
for(int i=1;i<=N;i++)//二叉查找树的建立
{
if(i==1)
{
tree[1]=node[i];
continue;
}
int index=1;
while(tree[index]!=0)
index=(node[i]>tree[index])?(2*index+1):(2*index);
tree[index]=node[i];
}
cur=1;
printf("前序遍历\n");
print_01(1);
printf("\n");
cur=1;
printf("中序遍历\n");
print_02(1);
printf("\n");
cur=1;
printf("后序遍历\n");
print_03(1);
printf("\n");
}
return 0;
}
// 调用递归输出前序、中序、后序遍历解析
void print_01(int index)//调用递归输出,前序遍历
{
if(cur>N)
return ;
if(tree[index]==0)
return ;
printf("%d ",tree[index]);
cur++;
print_01(index*2);//判断左子树的语句在前,递归时优先判断是否存在符合条件的左子树;
print_01(index*2+1);
}
假设一棵树有九个节点,分别为6,3,8,5,2,9,4,7,10;
用树状结构表示为:
先不考虑打印语句,只看 print_01(index*2);print_01(index*2+1);这两个语句,起初,index指向数据6位置,先执行 print_01(index*2),来到数据3位置,在执行 print_01(index*2),来到数据2位置,在执行 print_01(index*2)发现数据2无左孩子,系统返回到数据2位置,在执行print_01(index*2+1),发现数据2无右孩子,系统接着返回到数据2位置,此时系统压栈的数据为6,3,2,2,2接着往上回溯,来到数据3位置,执行print_01(index*2+1),来到数据5位置,执行 print_01(index*2)语句来到数据4位置,在数据4位置执行 print_01(index*2)发现数据4无左孩子,系统返回到数据4位置,在执行print_01(index*2+1),发现数据4无右孩子,系统接着返回到数据4位置,此时系统压栈数据为6,3,2,2,2,3,5,4,4,4,系统接着上述操作由数据4位置返回到数据5位置,依次类推,总的压栈数据为6,3,2,2,2,3,5,4,4,4,5,5,3,6,8,7,7,7,8,9,9,10,10,10,9,8,6
而前序遍历,是先便利根节点,再依次遍历左子树和右子树,即按节点先便利的先输出,故printf()打印函数放在了print_01(index*2)和print_01(index*2+1)之前(6,3,2,2,2,3,5,4,4,4,5,5,3,6,8,7,7,7,8,9,9,10,10,10,9,8,6);
即打印出6,3,2,5,4,8,7,9,10;
同理,根据中序遍历的规则,是先打印左子树,在打印根节点,在打印右子树,即某一结点在第二次遍历时才打印,故printf()语句放在两个print_01()语句间(6,3,2,2,2,3,5,4,4,4,5,5,3,6,8,7,7,7,8,9,9,10,10,10,9,8,6)
即打印出2,3,4,5,6,7,8,9,10;
同理,后序遍历某一节点第三次遍历时才打印,printf()语句放在两个print_01()语句后(6,3,2,2,2,3,5,4,4,4,5,5,3,6,8,7,7,7,8,9,9,10,10,10,9,8,6);
即打印出2,4,5,3,7,10,9,8,6;
2链表表示二叉树
#include<iostream>
#include<cstdlib>
#include<cstdio>
using namespace std;
struct Tree
{
Tree *left;
Tree *right;
int data;
Tree *next;
};
Tree *Insert(Tree *root,int node)
{
Tree *new_node,*parent_node,*current_node;
new_node=(Tree*)malloc(sizeof(Tree));
new_node->data=node;
new_node->left=NULL;
new_node->right=NULL;
if(root==NULL)
return new_node;
current_node=root;
while(current_node!=NULL)
{
parent_node=current_node;
current_node=(node>current_node->data)?(current_node->right):(current_node->left);
}
if(node>parent_node->data)
parent_node->right=new_node;
else
parent_node->left=new_node;
//(node>parent_node->data)?(parent_node->right):(parent_node->left)=new_node;(此语句有误)
return root;
}
Tree *Create(int *node,int len)
{
Tree *root=NULL;
for(int i=1;i<=len;i++)
root=Insert(root,node[i]);
return root;
}
void print_01(Tree *root)//前序遍历;
{
if(root!=NULL)
{
printf("%d ",root->data);
print_01(root->left);
print_01(root->right);
}
}
void print_02(Tree *root)//中序遍历;
{
if(root!=NULL)
{
print_02(root->left);
printf("%d ",root->data);
print_02(root->right);
}
}
void print_03(Tree *root)//后序遍历;
{
if(root!=NULL)
{
print_03(root->left);
print_03(root->right);
printf("%d ",root->data);
}
}
int main()
{
int N;
while(cin>>N)
{
Tree *root=NULL;
int node[N+1];
for(int i=1;i<=N;i++)
cin>>node[i];
root=Create(node,N);
printf("***前序遍历***\n");
print_01(root);
printf("\n");
printf("***中序遍历***\n");
print_02(root);
printf("\n");
printf("***后序遍历***\n");
print_03(root);
printf("\n");
}
return 0;
}