【二叉树】层次遍历 队列实现

层遍历:从上到下、从左到右,如图所示:

图示为举例进行层遍历顺序


以上图为例,进行分析用栈还是队列

  • 如果用: 先进后出,想要输出顺序为先出左孩子后出右孩子的话,需要先进右后进左。

        入栈顺序:根 右 左 //必须通过根节点去保存左右孩子

        出栈:栈顶元素  //也就是后面入进来的先出

  • 举例上面的树图进行思路演绎:

        入栈:a

        出:a

        入:c b

        出:b

        入:c e d 

那么问题来了:此时应该遍历c 但是c被压在栈底出不来,只能先访问d和e,所以无法用栈进行层次遍历,只能用队列进行遍历

  • 队:判断队列是否为空,不为空时出队顺序为先出队头

           入队顺序:根节点、左孩子、右孩子

           出队顺序:出队头元素

  • 步骤:

        ① 将根节点入队 

        ② 判断树是否为空,不为空,则队头元素进行入出队

        ③ 将刚出队元素的左右孩子进行入队

        ④ 将①②③循环,直至队列为空时,停止

  • 举例上面的树图进行思路演绎:

(说明:灰色字母是已经出队元素,下划线代表目前队尾元素,蓝色是刚入队元素)

        入队:a   //首先判断树是否为空,不为空,则入树根a

        出队:a  //队头元素

        入:a b c  //先入a的左孩子b,再入a的右孩子c

        出:b   //队头元素

        入:a b c d e  //c还未出队所以还在,然后入b的左右孩子de

        出:c  //队头元素

        入:a b c d e f g  //de还未出队所以还在,然后入c的左右孩子fg

        出:d e f   //出队头元素d,d无左右孩子,继续出队头元素e,e无左右孩子,继续出队头元素f

        入: g  h  //入f的左右孩子gh

        出:g h  //出队头元素g,g无左右孩子,继续出队头元素h

        此时数组为空,说明入队的数据均已出队,所有节点访问完毕

伪代码:

 代码:

typedef struct node
{
    char value;//当前节点值
    struct node* left;//指向当前节点左孩子指针
    struct node* right;//指向当前节点右孩子指针
}Node; 

//层次遍历
void LevOrder(Node* root)
{
    queue<Node*> qq;//定义队列qq,存储指向每个结点的指针
    if(root == NULL)
    {
    return;
    }
    Node* front = NULL;//定义指向队头的指针
    qq.push(root);//将根节点入队
    while(!qq.empty())
    {
        front = qq.front();//先获取队头,才能在出队后访问其左右孩子
        qq.pop();//队头出队
        printf("%c", front->value);//输出队头的value
        //将当前front的左右孩子入队
        if (front->left != NULL)
            qq.push(front->left);
        //不用输出左右孩子,因为pop出队头后,左右孩子会成为新对头,每次只用输出队头元素
        if(front->right != NULL)
            qq.push(front->right);
    }
    printf("%\n");
}

完整代码:


typedef struct node
{
    char value;//当前节点值
    struct node* left;//指向当前节点左孩子指针
    struct node* right;//指向当前节点右孩子指针
}Node;

typedef struct tree
{
    Node* root;
}Tree;

void InitTree(Tree* t)
{
    t->root = NULL;
}

//先序遍历创建二叉树
Node* Create(const char*& str) //因为要修改字符串就加了引用&
{
    if (*str == '*')
        return NULL;
    else
    {
        Node* newnode = (Node*)malloc(sizeof(Node));
        if (newnode != NULL)
        {
            newnode->value = *str;
            newnode->left = Create(++str);
            newnode->right = Create(++str);
            return newnode;
        }
    }
}


//层次遍历
void LevOrder(Node* root)
{
    queue<Node*> qq;//定义队列qq,存储指向每个结点的指针
    if(root == NULL)
    {
    return;
    }
    Node* front = NULL;//定义指向队头的指针
    qq.push(root);//将根节点入队
    while(!qq.empty())
    {
        front = qq.front();//先获取队头,才能在出队后访问其左右孩子
        qq.pop();//队头出队
        printf("%c", front->value);//输出队头的value
        //将当前front的左右孩子入队
        if (front->left != NULL)
            qq.push(front->left);
        //不用输出左右孩子,因为pop出队头后,左右孩子会成为新对头,每次只用输出队头元素
        if(front->right != NULL)
            qq.push(front->right);
    }
    printf("\n");
}

int main()
{
    Tree t;
    InitTree(&t);
    const char* str = "ABDG**HI****CE*J**F**";
    t.root = Create(str);
    printf("层次遍历二叉树:\n");
    LevOrder(t.root);
    printf("\n");
}

    说明:上图代码的创建二叉树的思想:创建二叉树 

运行结果:

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值