一,前序遍历非递归:
根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下:
对于任一结点P:
1)访问结点P,并将结点P入栈;
2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;
3)直到P为NULL并且栈为空,则遍历结束。
void preOrder2(node *root) //非递归前序遍历
{
stack<node*> s;
node *p=root;
while(p!=NULL||!s.empty())
{
while(p!=NULL)//向左遍历直到叶子
{
cout<<p->data<<" ";
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
s.pop();
p=p->rchild;
}
}
cout<<endl;
}
二,中序遍历非递归
根据中序遍历的顺序,对于任一结点,优先访问其左孩子,而左孩子结点又可以看做一根结点,然后继续访问其左孩子结点,直到遇到左孩子结点为空的结点才进行访问,然后按相同的规则访问其右子树。因此其处理过程如下:
对于任一结点P,
1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;
2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;
3)直到P为NULL并且栈为空则遍历结束
void inOrder2(node *root) //非递归中序遍历
{
stack<node*> s;
node *p=root;
while(p!=NULL||!s.empty())
{
while(p!=NULL)//记录访问过的根节点
{
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
cout<<p->data<<" "; //访问栈顶
s.pop();
p=p->rchild; //将当前访问的元素的右孩子入栈
}
}
}
要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。
void postOrder3(node *root) //非递归后序遍历
{
stack<node*> s;
node *cur; //当前结点
node *pre=NULL; //前一次访问的结点
s.push(root);
while(!s.empty())
{
cur=s.top();
if((cur->lchild==NULL&&cur->rchild==NULL)||
(pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))
{
cout<<cur->data<<" "; //如果当前结点没有孩子结点或者孩子节点都已被访问过
s.pop();
pre=cur;
}
else
{
if(cur->rchild!=NULL)
s.push(cur->rchild);
if(cur->lchild!=NULL)
s.push(cur->lchild);
}
}
}
综合程序附录
#include "stdio.h" #include "stdlib.h" #include "stack.h" int count;//统计叶子节点个数 struct node { int data;//二叉树的节点值 node *lchild,*rchild;//左右孩子节点 }; /*不知道为什么 创建的时候需要返回值才 创建有效*/ node *createTree() { node *root; int data; printf("input data:"); scanf("%d",&data); //printf("output data:%d\n",data); if(data==0) root=NULL; else/*根左右 前序建立二叉树*/ { root=(node*)malloc(sizeof(node)); root->data=data; root->lchild=createTree(); root->rchild=createTree(); } return root; } void preOrder(node *root) { if(root==NULL) return; else//不是空 { printf("%d\n",root->data); preOrder(root->lchild); preOrder(root->rchild); } } void inOrder(node *root) { if(root==NULL) return; else//不是空 { inOrder(root->lchild); printf("%d\n",root->data); inOrder(root->rchild); } } void postOrder(node *root) { if(root==NULL) return; else//不是空 { postOrder(root->lchild); postOrder(root->rchild); printf("%d\n",root->data); } } void CountLeaves(node *root) { if(root==NULL) return; else//不是空 { if(root->lchild==NULL&&root->rchild==NULL) count++; CountLeaves(root->lchild); CountLeaves(root->rchild); } } int deepLength(node *root) { int deep1,deep2; if(root==NULL) return 0; else { deep1=deepLength(root->lchild); deep2=deepLength(root->rchild); if(deep1>deep2) return deep1+1;//这个地方一定是返回+1 else return deep2+1; } } void CountNodes(node *root) { if(root==NULL) return; else//不是空 { count++; CountNodes(root->lchild); CountNodes(root->rchild); } } void exchange(node *root) { if(root==NULL) return; else { exchange(root->lchild); exchange(root->rchild); node *temp=root->lchild; root->lchild=root->rchild; root->rchild=temp; } } void search(node *root,int x) { if(root==NULL) return ; else { if(root->data==x) { count++; printf("has\n"); } search(root->lchild,x); search(root->rchild,x); } } void preOrder2(node *root) //非递归前序遍历 { stack<node*> s; node *p=root; while(p!=NULL||!s.empty()) { while(p!=NULL)//向左遍历 直到叶子 { cout<<p->data<<" "; s.push(p); p=p->lchild; } if(!s.empty()) { p=s.top(); s.pop(); p=p->rchild; } } cout<<endl; } void inOrder2(node *root) //非递归中序遍历 { stack<node*> s; node *p=root; while(p!=NULL||!s.empty()) { while(p!=NULL) { s.push(p); p=p->lchild; } if(!s.empty()) { p=s.top(); cout<<p->data<<" "; s.pop(); p=p->rchild; } } } void postOrder3(node *root) //非递归后序遍历 { stack<node*> s; node *cur; //当前结点 node *pre=NULL; //前一次访问的结点 s.push(root); while(!s.empty()) { cur=s.top(); if((cur->lchild==NULL&&cur->rchild==NULL)|| (pre!=NULL&&(pre==cur->lchild||pre==cur->rchild))) { cout<<cur->data<<" "; //如果当前结点没有孩子结点或者孩子节点都已被访问过 s.pop(); pre=cur; } else { if(cur->rchild!=NULL) s.push(cur->rchild); if(cur->lchild!=NULL) s.push(cur->lchild); } } } /*一定要记住直接输入1 2 3 0 0 0 0 建立的是 左二叉树 平衡的应该是 1 2 0 0 3 0 0*/ int main() { node *root;//=(node*)malloc(sizeof(node));//这里不要初始化了 因为建立的时候要初始化 printf(" Please select what you want do\n"); printf("----------------------------------------------\n"); printf(" 1.前序创建二叉树\n"); printf(" 2.递归前序遍历二叉树\n"); printf(" 3.递归中序遍历二叉树\n"); printf(" 4.递归后序遍历二叉树\n"); printf(" 5.求叶节点个数\n"); printf(" 6.求树的高度\n"); printf(" 7.求二叉树节点个数\n"); printf(" 8.交换左右子树\n"); printf(" 9.查找有无某个节点\n"); printf(" 10.非递归前序遍历二叉树\n"); printf(" 11.非递归前序遍历二叉树\n"); printf(" 12.非递归前序遍历二叉树\n"); printf(" 15.退出\n"); int i; while(true) { scanf("%d",&i); switch(i) { case 1: root=createTree(); printf("create tree is finished please select what you want do next:\n");break; case 2: printf("Now outPut data in PreOrder:\n"); preOrder(root); printf("output is over please select again\n");break; case 3: printf("Now outPut data in inOrder:\n"); inOrder(root); printf("output is over please select again\n");break; case 4: printf("Now outPut data in postOrder:\n"); postOrder(root); printf("output is over please select again\n");break; case 5: count=0; CountLeaves(root); printf("The leaves's count is:%d\n",count); printf("output is over please select again\n");break;//叶子节点的个数 case 6: int deep=deepLength(root); printf("The tree's deepLength is:%d\n",deep); printf("output is over please select again\n");break; case 7: count=0; CountNodes(root); printf("The leaves's count is:%d\n",count); printf("output is over\n"); break;//求二叉树节点个数 case 8: exchange(root); break; case 9: printf("please input what you want search\n"); int x; scanf("%d",&x); count=0; search(root,x); if(count!=0) { printf("The tree has this root\n"); printf("output is over please select again\n"); } else { printf("The tree not has this root\n"); printf("output is over please select again\n"); } break; case 10: printf("Now outPut data in PreOrder:\n"); preOrder2(root); printf("output is over please select again\n");break; case 11: printf("Now outPut data in PreOrder:\n"); inOrder2(root); printf("output is over please select again\n");break; case 12: printf("Now outPut data in PreOrder:\n"); postOrder3(root); printf("output is over please select again\n");break; case 15: exit(0); break;//包含在stdlib.h当中 } } return 0; }