二叉树的遍历
一棵二叉树的基本操纵,在这片博客里有记录:点击打开链接
一棵二叉树的多种建树方法也在这篇博客中:点击打开链接
一颗线索化的树操作在:点击打开链接
今天这篇博客就是教你多种遍历的方法。咋们平时都知道一棵树的基本遍历就是先序,中序,后序。那么你也许会直接想起递归的实现遍历,那么你到底还会不会其他的方法。
今天这里教你三种方法。
第一种:递归的二叉树遍历。
第二种:用栈实现二叉树的遍历
第三种:栈加计数来实现二叉树的遍历
第四种:是线索化遍历
注:附件其他的遍历方式;
第一种的三种遍历方式
//先序遍历
void Pretra(BtNode *p)
{
if(p != NULL)
{
cout<<p->data<<" ";
Pretra(p->leftchild);
Pretra(p->rightchild);
}
}
//中序遍历
void Midtra(BtNode *p)
{
if(p != NULL)
{
Midtra(p->leftchild);
cout<<p->data<<" ";
Midtra(p->rightchild);
}
}
//后序遍历
void Lasttra(BtNode *p)
{
if(p != NULL)
{
Lasttra(p->leftchild);
Lasttra(p->rightchild);
cout<<p->data<<" ";
}
}
第二种:
/先序遍历
void NicePreOrder(BtNode *p)
{
BtNode *s = NULL;
stack<BtNode* > st;
st.push(p);
while(!st.empty())
{
BtNode *node = st.top();st.pop();
cout<<node->data<<" ";
if( node->rightchild != NULL)
{
st.push(node->rightchild);
if(node->leftchild != NULL)
{
st.push(node->leftchild);
}
}
}
cout<<endl;
}
//中序遍历
void NiceMiOrder(BtNode *p)
{
BtNode *s = NULL;
stack<BtNode* > st;
while(p != NULL || !st.empty())
{
while(p != NULL)
{
st.push(p);
p = p->leftchild;
}
BtNode *node = st.top();st.pop();
cout<<node->data<<" ";
p = node->rightchild;
}
cout<<endl;
}
//后序遍历
void NiceLaOrder(BtNode *p)
{
BtNode *s = NULL;
stack<BtNode *> st;
BtNode *tag = NULL;
while(p != NULL || !st.empty())
{
while(p != NULL)
{
st.push(p);
p = p->leftchild;
}
BtNode *node = st.top();st.pop();
if(node->rightchild == NULL || node->rightchild == tag)
{
cout<<node->data<<" ";
tag = node;
node = NULL;
}
else
{
st.push(node);
p = node->rightchild;
}
}
cout<<endl;
}
第三种:技术遍历
看着上面的图,我来先介绍一下。每一个节点入栈的时候,默认计数都是0。每出一次栈,都会计数加一。那么那么你的第一次计数为1的时候,我们开始访问他的左子树,当计数为2的时候,我们开始访问他的右子树。
struct SkNode
{
BtNode *pnode;
int popnum;
SkNode(BtNode *p=NULL,int num=0):pnode(p),popnum(num){}
};
//先序遍历
void NicePreOrder1(BtNode *p)
{
BtNode *s = NULL;
stack<SkNode > st;
st.push(SkNode(p));
while(!st.empty())
{
SkNode node = st.top();st.pop();
if(++node.popnum == 1)
{
cout<<node.pnode->data<<" ";
if( node.pnode->rightchild != NULL)
{
st.push(node);
}
if( node.pnode->leftchild != NULL)
{
st.push(SkNode(node.pnode->leftchild));
}
}
else if(node.popnum == 2)
{
st.push(SkNode(node.pnode->rightchild));
}
}
cout<<endl;
}
//中序遍历
void NiceMiOrder1(BtNode *p)
{
BtNode *s = NULL;
stack<SkNode> st;
st.push(SkNode(p));
while(!st.empty())
{
SkNode node = st.top();st.pop();
if(++ node.popnum == 2)
{
cout<<node.pnode->data<<" ";
if(node.pnode->rightchild != NULL)
{
st.push(SkNode(node.pnode->rightchild));
}
}
else if(node.popnum == 1)
{
st.push(node);
if(node.pnode->leftchild != NULL)
st.push(SkNode(node.pnode->leftchild));
}
}
cout<<endl;
}
//后序遍历
void NiceLaOrder1(BtNode *p)
{
BtNode *s = NULL;
stack<SkNode> st;
st.push(SkNode(p));
while(!st.empty())
{
SkNode node = st.top();st.pop();
if(++node.popnum == 3)
{
cout<<node.pnode->data<<" ";
}
else
{
st.push(node);
if(node.popnum == 1 && node.pnode->leftchild != NULL)
{
st.push(SkNode(node.pnode->leftchild));
}
else if(node.popnum == 2 && node.pnode->rightchild != NULL)
{
st.push(SkNode(node.pnode->rightchild));
}
}
}
cout<<endl;
}
最后介绍一下,逐层访问每一个节点;
//层次打印这个二叉树
//1.在层次打印的时候,要先进先出。那么就用容器queue
void NiceleveDrder(BtNode *p)
{
if(p == NULL) return ;
queue<BtNode *> qu;
qu.push(p);
while(!qu.empty())
{
BtNode *node = qu.front();qu.pop();
cout<<node->data<<" ";
if(node->leftchild != NULL)
qu.push(node->leftchild);
if(node->rightchild != NULL)
qu.push(node->rightchild);
}
cout<<endl;
}
//2.可以调用打印第k层的函数来逐层打印
void NiceleveDrder1(BtNode *p)
{
int n = Depth(p);
for(int i = 1;i <= n;++i)
{
print_kleve_Item(p,i);
}
cout<<endl;
}
第四种:
//中序遍历一颗线索二叉树
BiThNode *First(BiThNode *p)
{
while(p != NULL && p->ltag != THREAD)
{
p = p->leftchild;
}
return p;
}
BiThNode *Next(BiThNode *p)
{
if(p == NULL) return NULL;
if(p->rtag == LINK)
{
BiThNode *ptr = First(p->rightchild);
return ptr;
}
else
{
return p->rightchild;
}
}
void ThreadMiinder(BiThNode *p)
{
for(BiThNode *s = First(p);s != NULL;s = Next(s))
{
cout<<s->data<<" ";
}
cout<<endl;
}