#include <iostream>
#include <stack>
using namespace std;
typedef struct node
{
int data ; //节点信息
struct node * leftChild ; //左孩子
struct node * rightChild ; //右孩子
}BiTreeNode,*BiTree;
/*
向树中添加新节点,建立查找二叉树
*/
void addTreeNode(BiTree &T,int value)
{
if(NULL == T)
{
T = new BiTreeNode ;
T->leftChild = NULL ;
T->rightChild = NULL ;
T->data = value ;
}
else
{
if(T->data > value)
{
addTreeNode(T->leftChild,value) ;
}
else if(T->data < value)
{
addTreeNode(T->rightChild,value) ;
}
else
{
cout<<"There has "<<value<<" in the tree!"<<endl;
}//end if( > <value)
}//end if(NULL == T)
}//end of addTreeNode
/*
创建树
*/
void buildTree(BiTree &T)
{
int b[] = {4,3,1,2,5,6,9,8} ;
for(int i = 0 ;i< sizeof(b)/sizeof(int);++i)
addTreeNode(T,b[i]) ;
}
//递归的前序遍历
void qianxubianli(BiTree T)
{
if(NULL == T)
return ;
else
{
cout<<T->data<<" ";
if(NULL !=T->leftChild)
qianxubianli(T->leftChild) ;
if(NULL != T->rightChild)
qianxubianli(T->rightChild) ;
}
}
//非递归前序遍历
//需要先压栈节点的右子树,在压栈左子树;
//因为前序遍历是先访问节点信息,在访问左子树,其次右子树;由于栈是后进后//出。所以应该先压栈右子树,再压栈左子树。
void qianxubianli2(BiTree T)
{
stack<BiTreeNode*> s ;
s.push(T) ;
while(!s.empty())
{
BiTreeNode* t = s.top() ;
s.pop() ;
cout<<t->data<<" " ; //访问节点信息
if(NULL != t->rightChild) //先将右孩子压栈
s.push(t->rightChild) ;
if(NULL != t->leftChild) //再将左孩子压栈
s.push(t->leftChild) ;
}
}
//递归的中序遍历
void zhongxubianli(BiTree T)
{
if(NULL==T)
return ;
else
{
if(NULL !=T->leftChild)
zhongxubianli(T->leftChild) ;//访问左子树
cout<<T->data <<" "; //访问节点信息
if(NULL != T->rightChild) //访问右子树
zhongxubianli(T->rightChild) ;
}
}
//非递归中序遍历
/*
思想:先循环遍历左子树,如果左子树不为空则压栈;当左子树为空时,且栈不为空时;访问栈顶元素p,pop栈顶元素,在访问p的右子树。
*/
void zhongxubianli2(BiTree T)
{
stack<BiTree > s ;
BiTree p = T ;
while(p || !s.empty())
{
if(NULL!=p) //沿着左子树一直往下搜索,直至左子树为空
{
s.push(p) ;
p = p->leftChild ;//
}
else //当左子树为空
{
p = s.top() ; //取出栈顶元素
s.pop() ; //删除栈顶元素
cout<<p->data<<" "; //访问节点信息
p=p->rightChild ; //搜索该节点的右子树
}
}
}
//递归的后序遍历
void houxubianli(BiTree T)
{
if(NULL == T)
return ;
if(NULL != T->leftChild)
houxubianli(T->leftChild) ;//访问节点的左子树
if(NULL != T->rightChild)
houxubianli(T->rightChild) ;//访问节点的右子树
cout<<T->data<<" " ; //访问节点的信息
}
/*
第一种思路:对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,
直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问,
因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,
当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。
这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,
只有在第二次出现在栈顶时,才能访问它。
因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。
typedef struct node1
{
BinTree *btnode;
bool isFirst;//标记
}BTNode;
void postOrder2(BinTree *root) //非递归后序遍历
{
stack<BTNode*> s;
BinTree *p=root;
BTNode *temp;
while(p!=NULL||!s.empty())
{
while(p!=NULL)//沿左子树一直往下搜索,直至出现没有左子树为空
{
BTNode *btn=(BTNode *)malloc(sizeof(BTNode));
btn->btnode=p;
btn->isFirst=true;
s.push(btn);
p=p->lchild;
}
if(!s.empty())
{
temp=s.top();
s.pop();
if(temp->isFirst==true) //表示是第一次出现在栈顶
{
temp->isFirst=false;
s.push(temp);
p=temp->btnode->rchild;
}
else //第二次出现在栈顶
{
cout<<temp->btnode->data<<" ";
p=NULL;
}
}
}
}
*/
/*
第二种思路:要保证根结点在左孩子和右孩子访问之后才能访问,
因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,
则可以直接访问它;或者P存在左孩子或者右孩子,
但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。
若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候
,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。
*/
//非递归后序遍历
void houxubianli2(BiTree T)
{
stack<BiTree > s ;
BiTree cur,pre=NULL;
s.push(T) ;
while( !s.empty())
{
cur = s.top() ;
//记录上一个节点是否已经访问过
//如果当前节点没有左右子节点,或者它的子节点已经被访问过
if((cur->leftChild == NULL && cur->rightChild == NULL)||(pre != NULL &&(pre == cur->leftChild || pre== cur->rightChild)))
{
cout<<cur->data<<" " ; //访问节点信息
s.pop() ;
pre = cur ; //记录当前访问的节点
}
else
{
if(cur->rightChild!=NULL)
s.push(cur->rightChild) ;//访问右子树
if(cur->leftChild!=NULL)
s.push(cur->leftChild) ;//访问左子树
}
}
}
int main()
{
BiTree T = NULL ;
buildTree(T) ;
cout<<"递归前序遍历:";
qianxubianli(T) ;
cout<<endl;
cout<<"非递归前序遍历:";
qianxubianli2(T) ;
cout<<endl;
cout<<"递归中序遍历:";
zhongxubianli(T) ;
cout<<endl;
cout<<"非递归中序遍历:";
zhongxubianli2(T) ;
cout<<endl;
cout<<"递归后序遍历:";
houxubianli(T) ;
cout<<endl;
cout<<"非递归后序遍历:";
houxubianli2(T) ;
cout<<endl;
system("pause") ;
}
二叉树的非递归遍历
最新推荐文章于 2020-09-24 10:59:45 发布