二叉树的遍历

二叉树是每个结点最多有两个子树的有序树。通常子树的根被称作“左子树”(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)存储:

lchilddatarchild

  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;
}

 

 



 

转载于:https://www.cnblogs.com/DonAndy/p/6028077.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值