在這總結了下二叉樹基本的幾種遍歷的遞歸與非遞歸的方法
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;
}