C++实现二叉树先中后序遍历(含栈)

  • 根据先序序列创建二叉树(#表示为null):ABD##EHJ##KL##M#N###CF##G#I##
  • 二叉树的先序遍历的递归算法
  • 二叉树的先序遍历的非递归算法
  • 二叉树的中序遍历的递归算法
  • 二叉树的中序遍历的非递归算法
  • 二叉树的后序遍历的递归算法
  • 二叉树的后序遍历的非递归算法
  • 求二叉树的结点个数
  • 求二叉树的叶子结点个数
  • 求二叉树中结点任意一结点的层次
  • 栈的初始化,进栈,入栈

/*
    * @Author: Lin Hongwei
    * @Date: 2021-12-04 09:05:03
 * @LastEditTime: 2021-12-04 18:50:53
 * @LastEditors: Lin Hongwei
    * @email: 1365755396@qq.com
    * @CSDN: https://blog.csdn.net/weixin_45429409
    * @Description: 
    */
#include <iostream>
typedef char TElementType; //将一个char类型用TElementType名重新定义
TElementType ch;

typedef struct BTNode{
    TElementType data;
    struct BTNode *lchild, *rchild;
} BTNode;//定义一个二叉树结构体

栈的内容
#define MaxSize 100//定义一个最大值常量

typedef struct{
    BTNode data[MaxSize]; //类型为TElementType(char),容量为MaxSize的数组
    int top;//栈顶指针
} SqStack;//定义一个栈SqStack结构体

//初始化栈
void InitStack(SqStack *&s){
    s = (SqStack *)malloc(sizeof(SqStack));//分配内存空间
    s->top = -1;//初始化栈顶指针为-1
}

//判断栈是否为空栈(栈顶指针为-1)
bool StackEmpty(SqStack *s){
    return (s->top == -1);
}
//入栈
bool Push(SqStack *&s, BTNode &e){
    //当栈满的时候返回false
    if (s->top == MaxSize - 1)
        return false;
    s->top++;//压入前先将栈顶指针+1
    s->data[s->top] = e;//将e赋值给栈对应位置后返回true
    return true;
}
//出栈
bool Pop(SqStack *s, BTNode &e){
    //当栈为空时返回false
    if (s->top == -1)
        return false;
    e = s->data[s->top]; //将栈顶的元素赋值给e
    s->top--;//栈顶指针-1,并返回true
    return true;
}

//

/**
 * 按先序序列输入二叉树中结点的值(一个字符),创建二叉树。
 */
void CreateBTree(BTNode *&T)
{
    cin >> ch;//获取控制台输入的字符
    if (ch == '#')T = NULL;//当输入为#时候表明该结点为空
    else{//非null是否初始化初始化一个结点,并将获取的字符传给结点的数据域,递归获取各自子右结点(先序方式)
        T = new BTNode();
        T->data = ch;
        CreateBTree(T->lchild);
        CreateBTree(T->rchild);
    }
}

/**
 * 返回结点的左孩子结点指针。
 */
BTNode *LchildNode(BTNode *T){
    return T->lchild;
}
/**
 *返回结点的右孩子结点指针。
 */
BTNode *RchildNode(BTNode *T){
    return T->rchild;
}

/**
 * 二叉树的先序遍历的递归算法。
 */
void PreOrder(BTNode *T){
    if (T){
        cout << T->data << " ";
        PreOrder(T->lchild);
        PreOrder(T->rchild);
    }
}

/**
 * 二叉树的先序遍历的非递归算法。
 * 读顺序:中 ,左 , 右
 */
void PreOrder1(BTNode *T){
    SqStack *S = NULL;
    InitStack(S);
    BTNode *copyT = T;           //拷贝一个树
    BTNode *oldT = new BTNode(); //初始化一个结点元素,用于存放入栈
    /**
     * (左有再存)
     * 先读本结点,再检查本结点是否有左结点,
     * 有左:将本结点存入栈,并读左节点,检查左结点是否有左节点
     * 无左:检查右结点
     * 有右:读右,并检查是否有左结点(重复上面)
     * 无右:取出栈中的元素,并找到它的右结点
     */
    while (copyT || !StackEmpty(S)){
        if (copyT){//该结点不为null的情况下,读取并检查是否有左结点
            cout << copyT->data << " ";//读取该结点
            if (copyT->lchild){
                //当左节点存在时,将本结点存入栈中,并将指针指向左结点
                Push(S, *copyT);
                copyT = copyT->lchild;
            }else{//不存左节点时,将指针指向右结点
                copyT = copyT->rchild;
            }
        }else{//该节点为null,进行出栈,并将指针指向该元素的右子节点
            Pop(S, *oldT);
            copyT = oldT->rchild;
        }
    }
}

/**
 * 二叉树的中序遍历的递归算法。
 */
void InOrder(BTNode *T){
    if (T){
        InOrder(T->lchild);
        cout << T->data << " ";
        InOrder(T->rchild);
    }
}

/**
 * 二叉树的中序遍历的非递归算法。
 * 读顺序:左 , 中 , 右
 */
void InOrder1(BTNode *T){
    SqStack *S = NULL;
    InitStack(S);
    BTNode *copyT = T;           //拷贝一个树
    BTNode *oldT = new BTNode(); //初始化一个结点元素,用于存放入栈
    /**
     * (非空就存)
     * 检查本结点是否有左结点,
     * 有:要先存后,检查左结点是否有左节点
     * 无:读取本结点,检查右结点(按上面循环)
     */
    while (copyT || !StackEmpty(S))
    {
        if (copyT){ //该结点不为null,进栈并将指针指向左子节点(进栈等待左子节点读完)
            Push(S, *copyT);
            copyT = copyT->lchild;
        }else{ //该节点为null,出栈并读,(左子节点为null,先读父结点),并将指针指向右指针(先父后右)
            Pop(S, *oldT);
            cout << oldT->data << " ";
            copyT = oldT->rchild;
        }
    }
}

/**
 * 二叉树的后序遍历的递归算法。
 * 读顺序:左 , 右 , 中
 */
void PostOrder(BTNode *T)
{
    if (T)
    {
        PostOrder(T->lchild);
        PostOrder(T->rchild);
        cout << T->data << " ";
    }
}

/**
 * 二叉树的后序遍历的非递归算法。
 * 读顺序:左 , 右 , 中 
 */
void PostOrder1(BTNode *T){
    SqStack *S = NULL;
    InitStack(S);
    BTNode *copyT = T;           //拷贝一个树
    BTNode *oldT = new BTNode(); //初始化一个结点元素,用于存放入栈
    /**
     * (取出清空子节点法:利用制造左右结点为null,当左右结点为null才读)
     * 检查是否为空,
     * 非空:将本结点存入栈中,并指向该结点的左子节点
     * 空:获取栈中的元素,并判断取出的元素,是否存在右子节点
     *    -- 存在右子节点:将指针指向该右结点后,将取出的元素右结点清除,并重新放入栈中
     *    -- 不存在右子节点:读取数据
     */
    while (copyT || !StackEmpty(S))
    {
        if (copyT){ //该结点不为null,进栈并将指针指向左子节点
            Push(S, *copyT);
            copyT = copyT->lchild;
        }else{ //该节点为null,出栈,检查取出栈元素的右子节点是否为null。不为null的话将指针指向该右子结点,并清空该元素的左右结点重新存入栈中。null的话读数据
            Pop(S, *oldT);
            if(oldT->rchild){
                copyT = oldT->rchild;
                oldT->rchild = NULL;
                Push(S, *oldT);
            }else{
                cout << oldT->data << " ";
            }
        }
    }
}

/**
 * 释放二叉树的所有结点。
 */
void DestroyBTree(BTNode *&T){ delete T;}

/**
 * 求二叉树的结点个数
 */ 
int Nodes(BTNode  *T){
    if(T==NULL)return 0;
    int leftNum = Nodes(T->lchild);
    int rightNum = Nodes(T->rchild);
    return leftNum+rightNum+1;
}
/**
 * 求二叉树的叶子结点个数
 */
int LeafNodes(BTNode  *T){
    int count = 0;
    if(T==NULL)return count;
    if(T->rchild==NULL&&T->lchild==NULL)count++;
    count += LeafNodes(T->lchild);
    count += LeafNodes(T->rchild);
    return count;
} 

/**
 * 求二叉树中结点任意一结点的层次
 */ 
int Level(BTNode  *T, TElementType x,int h){
    if(T==NULL) return 0;//当结点为NULL记录为0,也表示为找不到
    if (T->data==x) return h;//当找到结点后返回层次
    int l = Level(T->lchild,x,h+1);//记录在左节点中找到的层次
    if(l !=0) return l;
    return Level(T->rchild,x,h+1);//当左节点找不到时再进行右结点查找
}

int main(void)
{
    BTNode *T = NULL;
    //ABD##EHJ##KL##M#N###CF##G#I##
    CreateBTree(T);
    //由于是根据先序遍历生成的二叉树,所以在循环遍历的时候开头要参考先序遍历顺序(从上到下)
    cout << T << endl;
    cout << "先序递归遍历为:";
    PreOrder(T);
    cout << endl<< "先序的非递归遍历为:";
    PreOrder1(T);
    cout << endl<< "中序递归遍历为:";
    InOrder(T);
    cout << endl<< "中序非递归递归遍历为:";
    InOrder1(T);
    cout << endl << "后序递归遍历为:";
    PostOrder(T);
    cout << endl << "后序非递归遍历为:";
    PostOrder1(T);
    cout << endl << "结点数为:"<<Nodes(T);
    cout << endl << "叶子结点数为:"<<LeafNodes(T);

    int h = 1;
    TElementType x = 'D';
    h = Level(T,x,h);
    cout << endl << x << "所在的层次为:"<<h;
    return 0;
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值