二叉树的非递归建立(一)

我们参照递归过程中栈的变化情况适用堆栈来解决 。首先将二叉树进行扩展 ,如下图所示 :
这里写图片描述

然后按先序遍历的顺序输入节点的信息 ,根据输入的信息设置一个标志位 flag,
并初始化为1。 flag = 1表示现在需要创建当前节点的左孩子,flag = 2表示需要创建右孩子,flag = 3则表示当前节点的左右孩子都已经创建完毕,需要执行出栈操作,直到出栈节点不是当前栈顶节点的右孩子为止。
具体如下:
1) 当前要创建的节点值为′#′并且 flag=1,则置 flag=2,当前节点的左孩子创建节束,转向创建右孩子。
2) 当前要创建的节点值不为 ′#′并且 flag = 1,创建当前节点并作为栈顶节点的左孩子,同时将当前节点入栈。
3) 当前要创建的节点值不为 ′#′并且 flag = 2,创建当前节点并作为栈顶节点的右孩子,同时将当前节点入栈,然后置 flag=1,转向左孩子节点的创建。
4) 当前要创建的节点值为 ′#′并且 flag = 2,则置flag = 3,说明当前节点的父节点左右孩子节点处理节束,应将栈顶节点出栈 。如果出栈的节点依然等于栈顶节点的右孩子,说明当前栈顶节点的左右孩子节点也处理节束,栈顶节点继续出栈。直到当前栈顶节点的右孩子节点不等于出栈的节点为止。

实现代码如下:

#include <iostream>
using namespace std;
#include <deque>

typedef struct node
{
    char data;
    struct node *lchild;
    struct node *rchild;
}BiNode, *BiTree;


// 二叉树的建立(非递归)(按照先序遍历的顺序来生成一颗二叉树)
BiTree createBiTree()
{
    char ch[20];
    scanf("%s", ch);
    int len = (int)strlen(ch);

    BiTree stack[20]; // 用来存储节点地址的栈
    int top = -1; // 栈顶指针

    int flag = 1; // 标志位
    int i = 0;
    if (ch[i] == '#')
        return NULL;

    BiTree temp;

    BiTree root = new BiNode();
    root->data = ch[i++]; // 此处应该加一个判断首字符是否为‘#’的判断,保证根节点不为空。
    root->lchild = NULL;
    root->rchild = NULL;

    stack[++top] = root; // 根节点入栈


    while (i < len)
    {

        BiTree pNew = NULL;

        if (flag == 1) // 创建左孩子
        {
            if (ch[i] == '#')
                flag = 2;
            else
            {
                pNew = new BiNode();
                pNew->data = ch[i];
                pNew->lchild = NULL;
                pNew->rchild = NULL;

                temp = stack[top]; // 栈顶元素(取出栈顶元素赋予temp,注意,这不是出栈操作,因为栈顶指针top没有变)
                temp->lchild = pNew;
                stack[++top] = pNew; // 栈顶元素的左子树入栈
                flag = 1;

            }
        }
        else if (flag == 2) // 创建右孩子
        {
            if (ch[i] == '#')
                flag = 3;
            else
            {
                pNew = new BiNode();
                pNew->data = ch[i];
                pNew->lchild = NULL;
                pNew->rchild = NULL;

                temp = stack[top]; // 栈顶元素
                temp->rchild = pNew;
                stack[++top] = pNew; // 栈顶元素的右子树入栈
                flag = 1;
            }
        }
        else // 左右孩子都已经创建完毕
        {
            temp = stack[top--]; // 栈顶元素出栈,并修改栈顶指针
            while (top > 0 && stack[top]->rchild == temp) // 若此时栈中的元素个数仍大于1个,并且刚刚出栈的元素是当前栈顶元素的右子树,则继续让栈顶元素出栈,并修改栈顶指针。
                --top;


            flag = 2; // 跳出此while循环时,创建当前栈顶节点的右孩子,此时的i在ch[]中对应的数据刚好就是下一个待使用的数据,所以执行 --i是为了防止下面的 ++i跳过了该数据(即当前i对应的数据就是我们下一步创建右子树所应该使用的数据)。
            --i;
        }

        ++i;
    }

    return root;

}


// 二叉树的分层打印
void PrintTreeByLevel(BiTree T)
{
    if(T == NULL) return;

    deque<BiTree> q;
    q.push_back(T);

    int curLevelNum; // 当前层的节点数

    while (q.size())
    {
        curLevelNum = (int)q.size(); // 此处要做类型转换,因为size()返回值为size_type类型;
        while(curLevelNum-- > 0) // 一直访问到当前层的最后一个节点
        {
            BiTree tmp = q.front();

            q.pop_front();
            printf("%c ", tmp->data);

            if(tmp->lchild)
                q.push_back(tmp->lchild);
            if(tmp->rchild)
                q.push_back(tmp->rchild);
        }
        printf("\n"); // 当前层的元素输出完毕后,换行;
    }
}


int main(int argc, const char * argv[]) {

    BiTree T = createBiTree();

    PrintTreeByLevel(T); // 通过二叉树的分层打印,能更直观的验证创建的二叉树是否正确。

    return 0;
}

  • 8
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值