• 二叉树的遍历


    二叉树是每个结点最多有两个子树的有序树。通常子树的根被称作“左子树”(left subtree)和“右子树”(right subtree)。

    二叉树常被用作二叉查找树和二叉堆或是二叉排序树。二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。

    二叉树的基本性质:

      (1)二叉树的第i层至多有2的 i-1次方个结点(i>=1);

      (2)深度为k的二叉树至多有2^(k) -1个结点,最少有K个节点;

        最多的原因:2^(1-1)+2^(2-1)+2^(3-1)+....+2^(k-1)=(2^k)-1

        最少的原因:最少一层一个,K层k个节点,不一定全是斜的

      (3)对任何一棵二叉树T,如果其终端结点数(即叶子结点数)为n0,度为2的结点数为n2,则  n0 = n2 + 1。

        原因:若B为总分枝数,n是总节点数

        @1:n=n0+n1+n2

        @2:入枝的数量:B=n-1

        @3:出枝的数量:B=n1+2n2

        得出:n0=n2+1;

      当二叉树是完全二叉树时,可以用顺序存储结构:

      否则的话用顺序结构则会浪费空间,例如当深度是k的右斜树,只有K个节点,需要分配(2^k)-1个存储单元,浪费了(2^k)-1-K个空间

      一般情况下二叉树用二叉链表(binary linked list)存储:

    lchild data rchild

      lchild:左指针域

      data:数据域,存放节点的数据信息

      rchild:右指针域

      二叉树的节点用链式存储结构,其形式定义如下:

      BiNode.h如下:

    template <class T>
    struct BiNode  //结点结构
    {
        T data;
        BiNode<T> *lchild;
        BiNode<T> *rchild;
    };

    //StackElem.h
    template <class T> struct StackElem//非递归后序遍历时,栈元素结构 { BiNode<T> *ptr; int flag; };

    为了避免类的调用者访问BITree类的私有变量root,在勾走函数,析构函数,以及遍历函数中调用了相应的私有函数,

    //BiTree.h
    #include "BiNode.h" #include"StackElem.h" template <class T> class BiTree //二叉树类的定义 { public: BiTree();//二叉链表建立 ~BiTree(); void Prn();//二叉树的输出 void PreOrder();//前序遍历二叉树 void InOrder();//中序遍历二叉树 void PostOrder();//后序遍历二叉树 void LeverOrder();//层序遍历二叉树 private: BiNode<T> *root;//整个二叉树的根 BiNode<T> *creat();//二叉链表的生成 void release(BiNode<T> *bt);//二叉链表的撤销 void PrnIn(BiNode<T>* bt,int depth);//根为bt的二叉树的输出 void PreOrder(BiNode<T>* bt);//前序遍历根为bt的二叉树 void InOrder(BiNode<T>* bt);//中序遍历根为bt的二叉树 void PostOrder(BiNode<T>* bt);//后序遍历根为bt的二叉树 };
    前序遍历的思想:

    中序遍历的思想:

    后序遍历的思想:左孩子标志位是1,右孩子标志位是2


    //BiTree的实现BiTree.cpp:
    #include<iostream>
    #include"BiTree.h"
    using namespace std;
    
    template<class T>
    BiTree<T>::BiTree()
    {
        root=creat();
    }
    
    template<class T>
    BiNode<T> *BiTree<T>::creat()//二叉链表的生成
    {
        BiNode<T> *bt;
        T ch;
        cin>>ch;
        if(ch=='#') bt=NULL;
        else
        {
            bt=new BiNode<T>;
            bt->data=ch;
            bt->lchild=creat();
            bt->rchild=creat();
        }
        return bt;
    }
    
    template <class T>  //析构函数
    BiTree<T>::~BiTree()
    {
        release(root);
    }
    
    template <class T>
    void BiTree<T>::release(BiNode<T> *bt)//二叉链表的撤销
    {
        if(bt!=NULL)
        {
            release(bt->lchild);
            release(bt->rchild);
            delete bt;
        }
        else
            return;
    }
    
    template <class T>
    void BiTree<T>:: Prn()//二叉树的输出
    {
       PrnIn(root,1);
    }
    
    template <class T>
    void BiTree<T>::PrnIn(BiNode<T> *bt,int depth)//根为bt的二叉树的输出
    {
        if(bt!=NULL)
        {
            PrnIn(bt->rchild,depth+1);
            for(int i=0;i<4*(depth-1);i++)
                cout<<" ";
            cout<<"--"<<bt->data<<endl;
            PrnIn(bt->lchild,depth+1);
        }
        else return ;
    }    
    
    //前序遍历算法实现
    template <class T>
    void BiTree<T>::PreOrder()
    {
        PreOrder(root);
    }
    
    //**************前序遍历
    //template <class T>    //前序遍历递归算法
    //void BiTree<T>::PreOrder(BiNode<T> *bt)
    //{
    //    if(bt!=NULL)
    //    {
    //        cout<<bt->data;
    //        PreOrder(bt->lchild);
    //        PreOrder(bt->rchild);
    //    }
    //    else return;
    //}
    
    template <class T>    //前序遍历非递归算法
    void BiTree<T>::PreOrder(BiNode<T> *bt)
    {
        BiNode<T> * s[100]; //
        int top=-1;
        while(top!=-1 || bt!=NULL)
        {
            while(bt!=NULL)
            {
                cout<<bt->data;
                s[++top]=bt;
                bt=bt->lchild;
            }
            if(top!=-1)
            {
                bt=s[top--];
                bt=bt->rchild;
            }
        }
    }
    
    //**************中序遍历
    template <class T>    
    void BiTree<T>::InOrder()
    {
        InOrder(root);
    }
    
    template <class T>    //中序遍历递归算法
    void BiTree<T>::InOrder(BiNode<T>* bt)
    {
        if(bt!=NULL)
        {
            InOrder(bt->lchild);
            cout<<bt->data;
            InOrder(bt->rchild);
        }
        else return ;
    }
    
    
    //template <class T>    //中序遍历非递归算法
    //void BiTree<T>::InOrder(BiNode<T> *bt)
    //{
    //        BiNode<T> *  s[100];//定义一个栈
    //        int top=-1;
    //        while(bt!=NULL||top!=-1)
    //        {
    //            while(bt!=NULL)
    //            {
    //                s[++top]=bt; //根指针Bt入栈
    //                bt=bt->lchild;
    //            }
    //            if(top!=-1) //栈非空
    //            {
    //                bt=s[top--];
    //                cout<<root->data;
    //                bt=bt->rchild;
    //            }
    //        }
    //}
    
    
    //**************后序遍历
    template <class T>
    void BiTree<T>::PostOrder()
    {
      PostOrder(root);
    }
    
    //template <class T>  //后序遍历递归算法
    //void BiTree<T>::PostOrder(BiNode<T>* bt)
    //{
    //    if(bt!=NULL)
    //    {
    //        PostOrder(bt->lchild);
    //        PostOrder(bt->rchild);
    //        cout<<bt->data;
    //    }
    //    else return ;
    //}
    
     //后序遍历非递归算法
    template <class T> 
    void BiTree<T>::PostOrder(BiNode<T> *bt)
    {
        StackElem<T> s[100];
        int top=-1;
        while(bt!=NULL|| top!=-1)//2个条件都不成立才退出循环
        {
            while(bt!=NULL)
            {
                ++top;
                s[top].ptr=bt;//压栈
                s[top].flag=1;//设置标志位
                bt=bt->lchild;////继续访问左子树
            }
            while(top!=-1 && s[top].flag==2) //栈顶标志位是2,弹栈输出
            {
                cout<<s[top--].ptr->data;
            }
            if(top!=-1)//栈顶标志位是1,栈顶标志位设2,bt指向有右孩子
            {
                s[top].flag=2;
                bt=s[top].ptr->rchild;
            }
        }
    }
    
    
    
    
    //以下为层序遍历算法的实现
    template <class T>
    void BiTree<T>::LeverOrder()
    {
        BiNode<T> *bt;
        int front=0;
        int rear=0;
        BiNode<T>* s[20];
        if(root==NULL) return;
        rear=(rear+1)%20;
        s[rear]=root;
        while(front!=rear)
        {
            front=(front+1)%20;
            bt=s[front];
            cout<<bt->data;
            if(bt->lchild!=NULL)
            {
                rear=(rear+1)%20;
                s[rear]=bt->lchild;
            }
            if(bt->rchild!=NULL)
            {
                rear=(rear+1)%20;
                s[rear]=bt->rchild;
            }
        }
    }

    测试Main函数

    #include"BiTree.cpp"
    void main()
    {
        BiTree<char> tree;
        //tree.creat();
        cout<<"二叉树的输出:"<<endl;
        tree.Prn();
        cout<<endl;
        
        cout<<"前序遍历输出:"<<endl;
        tree.PreOrder();
        cout<<endl;
    
        cout<<"中序遍历输出:"<<endl;
        tree.InOrder();
        cout<<endl;
    
        cout<<"后序遍历输出:"<<endl;
        tree.PostOrder();
        cout<<endl;
    
        cout<<"层序遍历输出:"<<endl;
        tree.LeverOrder();
        cout<<endl;
    }


  • 相关阅读:
    解决 src/MD2.c:31:20: fatal error: Python.h: No such file or directory安装包错误
    Java 保存对象到文件并恢复 ObjectOutputStream/ObjectInputStream
    Elasticsearch安装配置和测试
    [知识图谱] 环境配置:Java8 + Maven3 + HBase + Titan
    Java8安装配置
    MongoDB 安装、运行、使用、数据恢复
    Java堆空间溢出解决方法 Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    服务器重装和配置:Ubuntu16.04 + Anaconda3 + GTX1080驱动 + CUDA8 + cuDNN + 常用工具安装
    [Linux] 输出文件的指定行
    [Linux] sed命令使用之在文件中快速删除/增加指定行
  • 原文地址:https://www.cnblogs.com/DonAndy/p/6028077.html
Copyright © 2020-2023  润新知