在这总结了下二叉树基本的几种遍历的递归与非递归的方法
1.按层遍历
思路:利用队列先进先出的思想,先让根节点入队,然后根节点出队,接着让根节点的左右子女依次入队,然后以此循环。
//按层遍历,利用队列
void printtree(BTNode *root,int n)
{
int f=0;
int r=0; //f为队列的头部标识(直指对头元素),r为尾部标识(指向最后一个元素的下一个位置)
BTNode *p;
BTNode **F=(BTNode **)malloc(n*sizeof(BTNode *)); //动态建立一个数组,用来存储节点指针(即为一个队列)
r=(r+1)%n;F[r]=root; //根节点入队
while(r!=f) //r=f,队列为空的条件
{
f=(f+1)%n; // 根节点出队
p=F[f];
printf("%5d",p->date);
if(p->left) //若根的左子女非空,则入队
{
r=(r+1)%n;
F[r]=p->left;
}
if(p->right) //若根的右子女非空,则入队
{
r=(r+1)%n;
F[r]=p->right;
}
}
}
2.前序非递归遍历
思路:利用栈先进后出的思想,先让根节点入栈,然后根节点出栈,
若根节点的左右子女不为空,则先将右子女压栈,再将左子女压栈,然后将此时栈中的栈 顶节点作为根节点,循环操作。
如果根节点左右节点为空,则直接将此时栈中的栈顶节点作为根节点,循环操作。
//先序非递归遍历 ,利用栈。
void printtree1(BTNode *root,int n)
{
int top=-1; //top为栈头标识
BTNode *p;
BTNode **F=(BTNode **)malloc(n*sizeof(BTNode *)); //动态建立一个数组,用来存储节点指针(即为一个栈)
top++; //根压栈
F[top]=root;
while(top+1) //栈不为空
{
top--; //根出栈
p=F[top+1];
printf("%5d",p->date);
// 注意!!,必须先压右子女,再压左子女!!!
if(p->right) //根的右子女若不为空,则压栈
F[++top]=p->right;
if(p->left) //根的左子女若不为空,则压栈
F[++top]=p->left;
}
printf("\n");
}
3.中序非递归遍历
思路:对于任意一个节点p,先将p的左子女从上往下依次压栈(p=p->left),直到左子女为空,即p=null
然后取栈顶结点,出栈,
将栈顶结点的右子女压栈
循环操作,直到栈为空结束
//中序非递归遍
void printtree3(BTNode *root,int n)
{
int top=0; //top为栈头标识
BTNode *p;
BTNode **F=(BTNode **)malloc(n*sizeof(BTNode *)); //动态建立一个数组,用来存储节点指针(即为一个栈)
p=root;
while(p||top) //如果p节点不为空或栈不为空
{
while(p) //将p的左子女依次入栈
{
F[++top]=p;
p=p->left;
}
if(top)
{
p=F[top];
printf("%5d",p->date);
top--;
p=p->right;
}
}
printf("\n");
}
4后序非递归遍历
思路: 先将根节点压栈
若根节点的左右子女都为空,或者左右子女都已出栈,则根节点出栈
否则先将右子女压栈,再将左子女压栈
取栈顶结点重复二三操作
//后序非递归遍历
void printtree5(BTNode *root,int n)
{
int top=0; //top为栈头标识
BTNode *p;
BTNode *q=null;
BTNode **F=(BTNode **)malloc(n*sizeof(BTNode *)); //动态建立一个数组,用来存储节点指针(即为一个栈)
F[++top]=root; //将根节点入栈
while(top)
{
p=F[top];
if((p->left==null&&p->right==null)||(q&&(q==p->left||q==p->right)))
{
top--;
printf("%5d",p->date);
q=p;
}
else
{
if(p->right)
{
//p=p->right; //
F[++top]=p->right;
}
if(p->left)
{
//p=p->left;
F[++top]=p->left;
}
}
}
printf("\n");
}
5.前,中,后递归遍历
//先序递归遍历
void printtree2(BTNode *root)
{
if(root)
{
printf("%5d",root->date);
printtree2(root->left);
printtree2(root->right);
}
}
//中序递归遍历
void printtree4(BTNode * root)
{
if(root)
{
printtree4(root->left);
printf("%5d",root->date);
printtree4(root->right);
}
}
//后序递归遍历
void printtree6(BTNode * root)
{
if(root)
{
printtree6(root->left);
printtree6(root->right);
printf("%5d",root->date);
}
}
完整代码如下,我顺便建立的二叉查找树
#include<stdio.h>
#include<stdlib.h>
#define null 0
typedef struct Node
{
int date;
struct Node * left;
struct Node * right;
}BTNode;
//建立二叉查找树
BTNode *settree(int *a,int n)
{
BTNode *root,*t,*p,*c;
int i;
root=(BTNode *)malloc(sizeof(BTNode));
root->date=a[0]; //初始化根节点
root->left=root->right=null;
for(i=1;i<n;i++) //添加其他节点
{
p=(BTNode *)malloc(sizeof(BTNode));
p->date=a[i];
p->left=p->right=null;
t=root;
while(t)
{
c=t;
if(t->date>p->date)
{
t=t->left;
}
else
{
t=t->right;
}
}
if(c->date>p->date)
{
c->left=p;
}
else
{
c->right=p;
}
}
return root;
}
//按层遍历,利用队列
void printtree(BTNode *root,int n)
{
int f=0;
int r=0; //f为队列的头部标识(直指对头元素),r为尾部标识(指向最后一个元素的下一个位置)
BTNode *p;
BTNode **F=(BTNode **)malloc(n*sizeof(BTNode *)); //动态建立一个数组,用来存储节点指针(即为一个队列)
r=(r+1)%n;F[r]=root; //根节点入队
while(r!=f) //r=f,队列为空的条件
{
f=(f+1)%n; // 根节点出队
p=F[f];
printf("%5d",p->date);
if(p->left) //若根的左子女非空,则入队
{
r=(r+1)%n;
F[r]=p->left;
}
if(p->right) //若根的右子女非空,则入队
{
r=(r+1)%n;
F[r]=p->right;
}
}
}
//先序非递归遍历 ,利用栈。
void printtree1(BTNode *root,int n)
{
int top=-1; //top为栈头标识
BTNode *p;
BTNode **F=(BTNode **)malloc(n*sizeof(BTNode *)); //动态建立一个数组,用来存储节点指针(即为一个栈)
top++; //根压栈
F[top]=root;
while(top+1) //栈不为空
{
top--; //根出栈
p=F[top+1];
printf("%5d",p->date);
// 注意!!,必须先压右子女,再压左子女!!!
if(p->right) //根的右子女若不为空,则压栈
F[++top]=p->right;
if(p->left) //根的左子女若不为空,则压栈
F[++top]=p->left;
}
printf("\n");
}
//先序递归遍历
void printtree2(BTNode *root)
{
if(root)
{
printf("%5d",root->date);
printtree2(root->left);
printtree2(root->right);
}
}
//中序非递归遍
void printtree3(BTNode *root,int n)
{
int top=0; //top为栈头标识
BTNode *p;
BTNode **F=(BTNode **)malloc(n*sizeof(BTNode *)); //动态建立一个数组,用来存储节点指针(即为一个栈)
p=root;
while(p||top) //如果p节点不为空或栈不为空
{
while(p) //将p的左子女依次入栈
{
F[++top]=p;
p=p->left;
}
if(top)
{
p=F[top];
printf("%5d",p->date);
top--;
p=p->right;
}
}
printf("\n");
}
//中序递归遍历
void printtree4(BTNode * root)
{
if(root)
{
printtree4(root->left);
printf("%5d",root->date);
printtree4(root->right);
}
}
//后序非递归遍历
void printtree5(BTNode *root,int n)
{
int top=0; //top为栈头标识
BTNode *p;
BTNode *q=null;
BTNode **F=(BTNode **)malloc(n*sizeof(BTNode *)); //动态建立一个数组,用来存储节点指针(即为一个栈)
F[++top]=root; //将根节点入栈
while(top)
{
p=F[top];
if((p->left==null&&p->right==null)||(q&&(q==p->left||q==p->right)))
{
top--;
printf("%5d",p->date);
q=p;
}
else
{
if(p->right)
{
//p=p->right; //
F[++top]=p->right;
}
if(p->left)
{
//p=p->left;
F[++top]=p->left;
}
}
}
printf("\n");
}
//后序递归遍历
void printtree6(BTNode * root)
{
if(root)
{
printtree6(root->left);
printtree6(root->right);
printf("%5d",root->date);
}
}
int main()
{
int a[10]={10,6,14,3,8,19,4,7,18,21};
BTNode *r;
r=settree(a,10);
printtree(r,10);
printf("\n");
printtree1(r,10);
printtree2(r);
printf("\n");
printtree3(r,10);
printtree4(r);
printf("\n");
printtree5(r,10);
printtree6(r);
return 0;
}