《数据结构》学习记录(10):二叉树遍历

一、二叉树遍历的概念

按照一定次序访问树中所有结点,并且每个结点仅被访问一次的过程。

遍历是二叉树最基本的运算,是二叉树中其他运算的基础。

二、 先序遍历

过程:

  • 访问根结点;
  • 先序遍历左子树;
  • 先序遍历右子树。
struct BTNode
{
    QChar data;
    BTNode * lchild{nullptr};
    BTNode * rchild{nullptr};
};

//先序遍历(递归算法)
void PreOrder(BTNode * node)
{
    if (node)
    {
        qDebug()<<node->data;
        PreOrder(node->lchild);
        PreOrder(node->rchild);
    }
}

//创建二叉树
void CreateBTNode(BTNode * & root,QString binaryTreeBracketNotationString)
{
    root = nullptr;
    enum class processTreeType//当前字符处理的类型
    {
        leftChildTree,
        rightChildTree,
        noChildTree
    };
    processTreeType nowNodeProcessTreeType{processTreeType::noChildTree};

    BTNode * currentNode{nullptr};//当前创建的结点
    QStack<BTNode*> stack;
    for(const auto & element : qAsConst(binaryTreeBracketNotationString))
    {
        if(element == '(')//表示一棵左子树的开始,即将前面刚创建的结点作为双亲结点进栈
        {
            stack.push(currentNode);
            nowNodeProcessTreeType = processTreeType::leftChildTree;
        }
        else if(element == ')')//表示一棵子树的结束
        {
            stack.pop();
        }
        else if(element == ',')//表示一棵右子树的开始
        {
            nowNodeProcessTreeType = processTreeType::rightChildTree;
        }
        else//字母,说明应该创建一个结点
        {
            currentNode = new BTNode;
            currentNode->data = element;

            if(!root)
                root = currentNode;
            else
            {
                switch (nowNodeProcessTreeType)
                {
                    case processTreeType::leftChildTree:stack.top()->lchild = currentNode;break;
                    case processTreeType::rightChildTree:stack.top()->rchild = currentNode;break;
                    case processTreeType::noChildTree:;break;
                }
            }
        }
    }
}

//递归销毁二叉树
void DestroyBT(BTNode * & node)
{
    if (!node)
        return;
    else
    {
        DestroyBT(node->lchild);
        DestroyBT(node->rchild);
        delete node;
        node = nullptr;
    }
}

    QString str = "A(B(D(M(N,),G(W(,H),))),C(E,F(P,Z(,K(Y,)))))";
    CreateBTNode(root,str);

三、中序遍历

过程:

  • 中序遍历左子树;
  • 访问根结点;
  • 中序遍历右子树。
// 中序遍历
void InOrder(BTNode * node)
{
    if (node)
    {
        InOrder(node->lchild);
        qDebug()<<node->data;
        InOrder(node->rchild);
    }
}

四、后序遍历

过程:

  • 后序遍历左子树;
  • 后序遍历右子树;
  • 访问根结点。
//后序遍历
void PostOrder(BTNode * node) 
{      
    if (node)  
    {      
        PostOrder(node->lchild);
        PostOrder(node->rchild);
        qDebug()<<node->data;
    }
}

五、获取二叉树的结点个数

int Nodes(BTNode * node)
{
    if (node)
        return Nodes(node->lchild) + Nodes(node->rchild) + 1;
    else
        return 0;
}

六、输出所有叶子结点

void DispLeaf(BTNode * node)
{
    if (node)
    {
        if (!node->lchild && !node->rchild)
            qDebug()<<node->data;
        DispLeaf(node->lchild);
        DispLeaf(node->rchild);
    }
}

七、获取元素所在的层数

int Level(BTNode * node, QChar x,int h)
{
    if (!node)
        return 0;
    else if (node->data == x)
        return h;
    else
    {
        int l = Level(node->lchild,x,h+1);//左子树递归查找
        if (l == 0)
            return Level(node->rchild,x,h+1);
        else
            return l;
    }
}

八、获取第n层的结点个数

int n = 0;
void Lnodenum(BTNode * node,int hight_of_node,int n)//(结点,参数1所处的结点,目标层数)
{
    if (node)
    {
        if (hight_of_node == n)
            n++;	//当前访问的结点在第k层时,n增1
        else if (hight_of_node < n)	//若当前结点层次小于k,递归处理左、右子树
        {
            Lnodenum(node->lchild,hight_of_node+1,n);
            Lnodenum(node->rchild,hight_of_node+1,n);
        }
    }
    else
        return;
}

九、获取某个结点是所有祖先结点

bool ancestor(BTNode * node,QChar x)
{
    if (!node)
        return false;
    else if ((node->lchild && node->lchild->data == x) ||
             (node->rchild && node->rchild->data == x))
    {
        qDebug()<<node->data;
        return true;
    }
    else if (ancestor(node->lchild,x) || 
             ancestor(node->rchild,x))  //递归子结点,有子结点满足条件
    {
        qDebug()<<node->data;
        return true;
    }
    else return false;
}

递归的思路是关注一个结点,考虑一个结点应该怎么样,不要关注其他结点。

十、层次遍历

从根结点开始,按从上到下、从左到右的顺序访问每一个结点。每一个结点仅访问一次。

#include <QQueue>
void LevelOrder(BTNode * node)
{
    QQueue<BTNode*> qu;
    qu.enqueue(node);
    while (!qu.isEmpty())
    {
        BTNode * p = qu.dequeue();//出队
        qDebug()<<p->data;

        if (p->lchild)
            qu.enqueue(p->lchild);
        if (p->rchild)
            qu.enqueue(p->rchild);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值