欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【二叉树】判断一棵二叉树是否是平衡二叉树/求一棵二叉树的镜像/对称的二叉树

程序员文章站 2022-05-16 14:56:34
...

求一颗二叉树的镜像

分析问题
镜像就是相反的东西,对于二叉树而言,将左子树改成右子树,右子树改成左子树。
递归实现1
可以采用递归的思路,前序遍历
依次交换当前根节点的左右孩子,再分别求左右子树镜像。
注:该方法改变了原来的树的结构

void Mirror(Node *pRoot)
{
    if(pRoot == NULL)
        return ;
    if(pRoot->left == NULL && pRoot->right == NULL)
        return ;
    //前序遍历,交换根节点的左右孩子。
    Node *tmp = pRoot->left;
    pRoot->left = pRoot->right;
    pRoot->right = tmp;
    //求左右子树的镜像
    if(pRoot->left)
        Mirror(pRoot->left);
    if(pRoot->right)
        Mirror(pRoot->right);   
}

递归实现2

思路:求出左右子树的镜像,交换左右子树的镜像。
//该方法没有改变树的结构

Node* Mirror(Node *pRoot)
{
    if(pRoot == NULL)
        retrun NULL;
    //求出左右子树的镜像
    Node *pLeft = Mirror(pRoot->left);
    Node *pRight = Mirror(pRoot->right);
    //交换左右子树
    pRoot->left = pRight;
    pRoot->right = pLeft;
    return pRoot;
}

非递归实现
非递归的实现,肯定要借助栈来实现。
根据递归实现1的前序遍历,实际上是前序遍历的非递归。

void Mirror_Nor(Node* pRoot)
{
    if(pRoot == NULL)
        return ;
    stack<Node *> s;
    s.push(pRoot);
    while(!s.empty())
    {
        Node *p =s.top();
        s.pop();
        //前序遍历,访问根节点,这是交换根节点的左右孩子
        if(p->left != NULL ||p->right != NULL)
        {
            Node* tmp = p->left;
            p->left = p->right;
            p->right = tmp;
        }
        //将右左子树入栈,
        //注:前序遍历这是先压右孩子,再压左孩子,这里无所谓
        if(p->right)
            s.push(p->right);
        if(p->left)
            s.push(p->left);
    }
}

判断一棵二叉树是否是平衡二叉树

分析问题
平衡二叉树又叫AVL树,左右子树的高度之差的绝对值不超过1,并且左右子树都是AVL树。

方法1、
可以求出利用AVL树的概念,求左右子树的高度,并确定左右子树是否为平衡二叉树。

//求二叉树的高度:左右子树最大值+1

size_t GetHeight(Node *pRoot)
{
    if(pRoot == NULL)
        return 0;
    if(pRoot->left == NULL && pRoot->right == NULL)
        return 1;
    int left = GetHeight(pRoot->left);
    int right = GetHeight(pRoot->right);
    return (left > right ? left +1:right +1);
}
bool IsBlance(Node *pRoot)
{
    if(pRoot == NULL)
        return true;
    int left = GetHeight(pRoot->left);
    int right = GetHeight(pRoot->right);
    int diff = left - right;
    if(diff >1 || diff <-1)
        return false;
    return IsBlance(pRoot->left) && IsBlance(pRoot->right);
}

方法2、
由于上述方法在求该结点的的左右子树深度时遍历一遍树,再次判断子树的平衡性时又遍历一遍树结构,造成遍历多次。因此方法二是一边遍历树一边判断每个结点是否具有平衡性。

//参数为指针,该参数为输出参数

bool IsBlance(Node *pRoot,int *height)
{
    if(pRoot == NULL)
    {
        *height = 0;
        return true;
    }
    int leftH = 0, rightH = 0;
    bool isLeft = IsBlance(pRoot_>left, &leftH);
    bool isRight = IsBlance(pRoot->right,&rightH);
    //左右子树都为AVL树,求出高度
    if(isLeft && isRight)
    {
        int diff = leftH - rightH;
        if(diff >= -1 && diff <= 1)
        {
            *height = (leftH>rightH?leftH+1:rightH+1);
            return true;
        }
        else
            return false;

    }
    return false;
}

对称的二叉树

判断一个二叉树是否是对称的,如果一棵二叉树和它的镜像一样没那么它是对称。

定义一个新的遍历方式:先遍历根节点,再遍历右子树,再遍历左子树
通过比较二叉树的前序遍历序列和对称前序遍历序列来判断二叉树是不是对称的,

bool isSymmetrical(Node* pRoot)
{
    return isSymmetrical(pRoot, pRoot);
}

bool isSymmetrical(Node* pRoot1,Node* pRoot2)
{
    if (pRoot1 == NULL && pRoot2 == NULL)
        return true;
    if (pRoot1 == NULL || pRoot2 == NULL)
        return false;
    if (pRoot1->val != pRoot2->val)
        return false;
    //比较pRoot1的左和pRoot2的右
    return isSymmetrical(pRoot1->left, pRoot2->right)
        && isSymmetrical(pRoot1->right, pRoot2->left);
}
相关标签: 二叉树