• 二叉树的三种遍历,递归与非递归


    1.先序遍历
    #include "stdafx.h"
    #include<iostream>
    using namespace std;
    typedef struct BTreeNode
    {
    	int data;
    	struct BTreeNode *lchild,*rchild;
    }BTree;
    int _tmain(int argc, _TCHAR* argv[])
    {
    	return 0;
    }
    void PreOrder(BTree *b)
    {       
    	if(b!=NULL)
    	{
    		printf("%c ",b->data);
    		PreOrder(b->lchild);
    		PreOrder(b->rchild);
    	}
    }
    

     2.中序遍历

    void InOrder(BTree *b)
    {
    	if(b!=NULL)
    	{
    		InOrder(b->lchild);
    		printf("%c ",b->data);
    		InOrder(b->rchild);
    	}
    }
    

      3.后序遍历

    void PostOrder(BTree *b)
    {
    	if(b!=NULL)
    	{
    		PostOrder(b->lchild);
    		PostOrder(b->rchild);
    		printf("%c ",b->data);
    	}
    }
    

     4.使用栈的非递归遍历

    非递归实现

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

         对于任一结点P:

         1)访问结点P,并将结点P入栈;

         2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;

            3)直到P为NULL并且栈为空,则遍历结束

    void preOrder2(BinTree *root)     //非递归前序遍历 
    {
        stack<BinTree*> s;
        BinTree *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;
            }
        }
    } 
    

     5.使用栈的中序

    void inOrder2(BinTree *root)      //非递归中序遍历
    {
        stack<BinTree*> s;
        BinTree *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;
            }
        }    
    }
    

     6.后序非递归

    思路:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。

    void postOrder3(BinTree *root)     //非递归后序遍历
    {
        stack<BinTree*> s;
        BinTree *cur;                      //当前结点 
        BinTree *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 "stdafx.h"
    #include<iostream>
    using namespace std;
    typedef struct BTreeNode
    {
    	int data;
    	struct BTreeNode *lchild,*rchild;
    }BTree;
    typedef struct stacknode
    {
    	BTree *node;
    	int tag;//tag为0表示结点左子女已经访问,为1表示右子女已经访问
    }stack;
    int _tmain(int argc, _TCHAR* argv[])
    {
    	return 0;
    }
    void PostOrder2(BTree *b)
    {
    	stack s[100];
    	int top=-1;
    	stack temp;//暂存结点信息
    	while(b||top>-1)
    	{
    		while(b)
    		{
    			temp.node=b;
    			temp.tag=0;//左结点已访问
    			s[++top]=temp;
    			b=b->lchild;
    		}
    		while(top&&s[top].tag==1){ //表示右子树访问完毕,所以访问根节点, 此处是while不是if  
    			//b = s[top --].node;
    			//cout << b->val << ' ';
    			/*之前是写这两行,但是会导致最后top为0时,p非空,所以会不断循环最外层的while(p||top)
    			如果要写这两行而不写下面那句的话,要采用do{}while(top);*/
    			cout << s[top --].node->data<< ' ';
    		}
    		if(top!=-1)
    		{
    			s[top].tag= 1; //右结点已访问           
    			b = s[top].node;           
    			b = b->rchild;
    		}
    	}
    }
    
  • 相关阅读:
    java.io.EOFException ValueOperations.increment()操作后,获取值时有的bug
    使用maven profile指定配置文件打包适用多环境
    关于3Q大战和反垄断
    在ECUG2010上的演讲稿
    让Windows7在启动时自动挂载虚拟磁盘
    也谈并行计算(一)C#版的Parallel.For实现
    给.NET的string类添加一个命令行参数分解的扩展
    顺序表 code
    很高兴开始博客之旅 code
    (原)前端知识杂烩(css系列)
  • 原文地址:https://www.cnblogs.com/tgkx1054/p/2628127.html
Copyright © 2020-2023  润新知