二叉树的遍历(递归),请参考该篇博客:二叉树的简单操作(递归实现)
这里有一篇很好的博客分享:二叉树前序、中序、后序遍历非递归写法的透彻解析
下面让我们看看非递归朝作,考虑到由于用C语言写的话 要自己用链表模拟栈,,,所以,此处改为C++代码了。。因为,可以直接调用STL中的stack。。。。。。
//#include<bits/stdc++.h>
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<string>
#include<math.h>
#include<stack>; //stack的头文件
using namespace std ;
typedef long long ll;
#define MAXN 100005
#define INF 0x3f3f3f3f
#define MALL (BiTnode *)malloc(sizeof(BiTnode));
typedef struct BiTnode
{
int data;//当然,你这里可以放你想要的数据
struct BiTnode *lchild, *rchild;
}BiTnode, *Bitree;
先序遍历:
首先,我们遍历左子树,边遍历边打印,并把根节点存入栈中,以后需借助这些节点进入右子树开启新一轮的循环。还得重复一句:所有的节点都可看做是根节点。
接下来就是:出栈,根据栈顶节点进入右子树。
void stackfirst_one(Bitree T)
{
if(T == NULL)
return;
Bitree p = T;
stack<Bitree>st;
while(p || !st.empty())
{
//边遍历边打印,并存入栈中,以后需要借助这些根节点(不要怀疑这种说法哦)进入右子树
while(p)
{
st.push(p);
cout << p->data;
p = p->lchild;
}
//当p为空时,说明根和左子树都遍历完了,该进入右子树了
if(!st.empty())
{
p = st.top();
st.pop();
p = p->rchild;
}
}
cout << '\n';
}
当然,书上可不是这样的:
void stackfirst_two(Bitree T)
{
if(T == NULL)
return ;
Bitree p = T;
stack<Bitree> st;
while(p || !st.empty())
{
if(p)
{
cout << p->data;
st.push(p);
p = p->lchild;
}
else
{
p = st.top();
st.pop();
p = p->rchild;
}
}
cout << '\n';
}
中序遍历。。。。
遇到一个结点,就把它压栈,并去遍历它的左子树;
当左子树遍历结束后,从栈顶弹出这个结点并访问它;
然后按其右指针再去中序遍历该结点的右子树。
void stackmiddle_one(Bitree T)
{
if(T == NULL)
return ;
Bitree p = T;
stack<Bitree>st;
while(p || !st.empty())
{
//一直遍历到左子树最下边,边遍历边保存根节点到栈中
while(p)
{
st.push(p);
p = p->lchild;
}
//当p为空时,说明已经到达左子树最下边,这时需要出栈了
if(!st.empty())
{
p = st.top();
st.pop();
cout << p->data;
//进入右子树,开始新的一轮左子树遍历(这是递归的自我实现)
p = p->rchild;
}
}
cout << '\n';
}
当然,数据结构上是这样的:
void stackmiddle_two(Bitree T)
{
if(T == NULL)
return ;
Bitree p = T;
stack<Bitree>st;
while(p || !st.empty())
{
if(p)
{
st.push(p);
p = p->lchild;
}
else
{
p = st.top();
st.pop();
cout << p->data;
p = p->rchild;
}
}
cout << '\n';
}
层次遍历(队列)
思路:
1、若根节点为空,直接返回;
2、若根节点非空,则将根节点入队,然后判断其左右子节点是否为空,若不为空,则压入队列。此时将根结点打印输出,并将根结点出队列。依次循环执行,直到队列为空。
void cenci(Bitree T)
{
if(T == NULL)
return;
queue<Bitree> que;
que.push(T);
while(!que.empty())
{
Bitree p = que.front();
cout << p->data << ' ';
que.pop();
if(p->lchild!=NULL)
que.push(p->lchild);
if(p->rchild!=NULL)
que.push(p->rchild);
}
cout << '\n';
}
总代码:
//#include<bits/stdc++.h>
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<string>
#include<math.h>
#include<stack>;
using namespace std ;
typedef long long ll;
#define MAXN 100005
#define INF 0x3f3f3f3f
#define MALL (BiTnode *)malloc(sizeof(BiTnode));
typedef struct BiTnode
{
char data;
struct BiTnode *lchild, *rchild;
} BiTnode, *Bitree;
void stackfirst_one(Bitree T)
{
if(T == NULL)
return;
Bitree p = T;
stack<Bitree>st;
while(p || !st.empty())
{
//边遍历边打印,并存入栈中,以后需要借助这些根节点(不要怀疑这种说法哦)进入右子树
while(p)
{
st.push(p);
cout << p->data;
p = p->lchild;
}
//当p为空时,说明根和左子树都遍历完了,该进入右子树了
if(!st.empty())
{
p = st.top();
st.pop();
p = p->rchild;
}
}
cout << '\n';
}
void stackfirst_two(Bitree T)
{
if(T == NULL)
return ;
Bitree p = T;
stack<Bitree> st;
while(p || !st.empty())
{
if(p)
{
cout << p->data;
st.push(p);
p = p->lchild;
}
else
{
p = st.top();
st.pop();
p = p->rchild;
}
}
cout << '\n';
}
void stackmiddle_one(Bitree T)
{
if(T == NULL)
return ;
Bitree p = T;
stack<Bitree>st;
while(p || !st.empty())
{
//一直遍历到左子树最下边,边遍历边保存根节点到栈中
while(p)
{
st.push(p);
p = p->lchild;
}
//当p为空时,说明已经到达左子树最下边,这时需要出栈了
if(!st.empty())
{
p = st.top();
st.pop();
cout << p->data;
//进入右子树,开始新的一轮左子树遍历(这是递归的自我实现)
p = p->rchild;
}
}
cout << '\n';
}
void stackmiddle_two(Bitree T)
{
if(T == NULL)
return ;
Bitree p = T;
stack<Bitree>st;
while(p || !st.empty())
{
if(p)
{
st.push(p);
p = p->lchild;
}
else
{
p = st.top();
st.pop();
cout << p->data;
p = p->rchild;
}
}
cout << '\n';
}
void first(Bitree T)
{
if(T)
{
cout << T->data;//这里你可以选择保存数据,,,
first(T->lchild);
first(T->rchild);
}
}
void middle(Bitree T)
{
if(T)
{
middle(T->lchild);
cout << T->data;//这里你可以选择保存数据,,,
middle(T->rchild);
}
}
void END(Bitree T)
{
if(T)
{
END(T->lchild);
END(T->rchild);
cout << T->data;
}
}
Bitree CreatBitree(Bitree &T)
{
char ch;
cin >> ch;
if(ch == '#')//若ch为 # ,则二叉树为空树。
T = NULL;
else
{
T = (BiTnode *)malloc(sizeof(BiTnode));
T->data = ch;
CreatBitree(T->lchild);//递归先序创建左子树
CreatBitree(T->rchild);//递归先序创建右子树
}
return T;
}
void Copy(Bitree T, Bitree &newT)//复制二叉树
{
if(T == NULL)
{
newT = NULL;
return ;
}
else
{
newT = (BiTnode *)malloc(sizeof(BiTnode));
newT->data = T->data;
Copy(T->lchild, newT->lchild);
Copy(T->rchild, newT->rchild);
}
}
int depth(Bitree T)//查询二叉树的深度
{
int m, n;
if(T == NULL)
return 0;
else
{
m = depth(T->lchild);
n = depth(T->rchild);
return m>n ? m+1 : n+1;
}
}
int Nodecount(Bitree T)//二叉树的总结点数
{
if(T == NULL)//如果是空树,则结点个数为0,递归结束
return 0;
else
return Nodecount(T->lchild)+Nodecount(T->rchild)+1;
// 否则结点个数为左子树的结点个数+右子树的结点个数+1(根结点)
}
int yezi(Bitree T)//求二叉树的叶子数/。。
{
if(T == NULL)
return 0;
else if(T->lchild == NULL && T->rchild == NULL)//左右为空,证明的叶子结点,返回1.
return 1;
else
return yezi(T->lchild)+yezi(T->rchild);
}
int main()
{
Bitree T;
T = CreatBitree(T);
int x = depth(T), y = Nodecount(T), z = yezi(T);
cout << "该二叉树的深度为:" << x << '\n';
cout << "该二叉树的结点数为:" << y << '\n';
cout << "该二叉树的叶子数为:" << z << '\n' << '\n';
cout << "先序遍历的结果为:" << '\n';
first(T); cout << '\n';
stackfirst_one(T);
stackfirst_two(T);
cout << "中序遍历的结果为:" << '\n';
middle(T); cout << '\n';
stackmiddle_one(T);
stackmiddle_two(T);
cout << "后序遍历的结果为:" << '\n';
END(T); cout << '\n';
return 0;
}