【100题】第四十二题 二叉树的非递归遍历

来源:互联网 发布:如何淘宝小二介入 编辑:程序博客网 时间:2024/05/16 15:33

一,前序遍历非递归:

       根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下:

        对于任一结点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;}

 
 
原创粉丝点击