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

二叉树的面试题之判断树

程序员文章站 2022-06-05 20:10:16
...

在前面,已经介绍过了,有关二叉树中的一些基本操作,如果大家对这些还不是十分熟悉,可以参考上一篇文章,有关二叉树的遍历方式:http://blog.csdn.net/aaronlanni/article/details/78698559
今天,主要介绍一些二叉树中,常见的一些操作:
一、判断一棵树是否是完全二叉树
完全二叉树:如果一棵具有N个结点的二叉树的结构与满二叉树的前N个结点的结构相同,称为完全二叉树。
不是完全二叉树的情况:只有右子树,没有左子树,此时,这种情况不是完全二叉树,具体分为几下几种:
(1)只有左子树,没有右子树,但是在当前结点的同一层上,其后结点的左或者右子树存在
(2)只有右子树,没有左子树
思路:利用标记法
(1)只有右,没有左—–>返回false
(2)只有左,没有右—–>将标记改为true—–>判断下一个结点是否存在左或者右—–>存在—–>返回false(反之,继续取队头)—–>队列中为空,没有退出,则返回true
(3)左右孩子均存在—->压入到队列中
具体情况如图所示:
二叉树的面试题之判断树
代码如下所示:
在此处,对函数在类中进行了一次封装,便于传递参数,对于封装的那一个函数,在这里就不一一给出了。
(一)代码一

bool _IsCompeteTree(pNode pRoot)
    {
        if (NULL == pRoot)
            return true;
        bool flag = false;
        pNode pCur = NULL;
        queue<pNode> q;
        q.push(pRoot);
        while (!q.empty())
        {
            pCur = q.front();
            q.pop();
            if (!flag)
            {
                if (pCur->_pLeft&&pCur->_pRight)
                {
                    q.push(pCur->_pLeft);
                    q.push(pCur->_pRight);
                }
                //当前结点存在左孩子,因此之后的结点不能存在右孩子(同一层上)
                if (pCur->_pLeft&&pCur->_pRight == NULL)
                {
                    q.push(pCur->_pLeft);
                    flag = true;
                }
                if (pCur->_pLeft == NULL&&pCur->_pRight)
                    return false;
            }
            else
            {
                if (pCur->_pLeft || pCur->_pRight)
                    return false;
            }
        }
        return true;
    }

(二)代码二

bool _IsCompeteTree1(pNode pRoot)
    {
        if (NULL == pRoot)
            return true;
        bool flag = false;
        pNode pCur = NULL;
        queue<pNode> q;
        q.push(pRoot);
        while (!q.empty())
        {
            pCur = q.front();

            //当前结点只有右----->不是
            if (pCur->_pLeft == NULL&&pCur->_pRight)
                return false;
            //当前结点只有左或者左右都不存在----->判断当前结点的下一个结点
            //判断当前结点的下一个结点
            if (flag&&(pCur->_pLeft != NULL || pCur->_pRight != NULL))
                return false;

            if (pCur->_pLeft == NULL || pCur->_pRight == NULL)
            {
                flag = true;
            }

            if (pCur->_pLeft)
                q.push(pCur->_pLeft);
            if (pCur->_pRight)
                q.push(pCur->_pRight);

            q.pop();
        }
        return true;
    }

(三)代码三

//左右子树分开
    bool _IsCompeteTree2(pNode pRoot)
    {
        if (NULL == pRoot)
            return true;
        bool flag = false;
        pNode pCur = NULL;
        queue<pNode> q;
        q.push(pRoot);
        while (!q.empty())
        {
            pCur = q.front();
            q.pop();
            if (pCur->_pLeft)
            {
                if (flag)
                    return false;
                q.push(pCur->_pLeft);
            }
            else
                flag = true;

            if (pCur->_pRight)
            {
                if (flag)
                    return false;
                q.push(pCur->_pRight);
            }
            else
                flag = true;
        }
        return true;
    }

以上判断是否是完全二叉树中,三种方法的大概思路是一致的,在第一种与第二种的思路一致,在第三种方法中,程序看上去比较简洁且比较容易实现,因此在这种方法中,效率能更高些。
测试代码如下所示:

void TestTree()
{
    char array[] = "abd###ce##f";
    BindaryTree<char> bt(array, strlen(array), '#');
    //树存在
    cout << "非空树1:"<<endl;
    if (bt.IsCompeteTree())
        cout << "是" << endl;
    else
        cout << "不是" << endl;

    if (bt.IsCompeteTree1())
        cout << "是" << endl;
    else
        cout << "不是" << endl;

    if (bt.IsCompeteTree2())
        cout << "是" << endl;
    else
        cout << "不是" << endl;

    char array1[] = "abd##c##f";
    BindaryTree<char> bt2(array1, strlen(array1), '#');
    //树存在
    cout << "非空树2:" << endl;
    if (bt2.IsCompeteTree())
        cout << "是" << endl;
    else
        cout << "不是" << endl;

    if (bt2.IsCompeteTree1())
        cout << "是" << endl;
    else
        cout << "不是" << endl;

    if (bt2.IsCompeteTree2())
        cout << "是" << endl;
    else
        cout << "不是" << endl;

    //空树
    BindaryTree<char> bt1;
    cout << "空树:"<<endl;
    if (bt1.IsCompeteTree())
        cout << "是" << endl;
    else
        cout << "不是" << endl;

    if (bt1.IsCompeteTree1())
        cout << "是" << endl;
    else
        cout << "不是" << endl;

    if (bt1.IsCompeteTree2())
        cout << "是" << endl;
    else
        cout << "不是" << endl;
}

结果如下所示:
二叉树的面试题之判断树

二、判断一棵二叉树是否是平衡树
平衡树:左子树-右子树的绝对值<1,则这样的树称为平衡树
思路:
(1)空树—->平衡
(2)只有一个结点—->平衡
(3)多个结点—–>左子树的高度-右子树的高度的绝对会<1
在这里,就有一个问题,就是求二叉树的高度,因此,在这里,顺便给出二叉树高度的求解思路:
(1)空树—->返回0
(2)只有一个结点—->返回1
(3)多个结点—->左子树与右子树中较高的树加上1即可
平衡树
二叉树的面试题之判断树
注意:在这里调用之时,调用的是经过封装的函数,从而为了传递参数的准确性。
具体代码实现如下所示:
封装前:

//判断一棵树是否是平衡二叉树
    bool IsBalanceTree()
    {
        if (_IsBalanceTree(_pRoot))
            return true;
        else
            return false;
    }

封装后

bool _IsBalanceTree(pNode pRoot)
    {
        if (pRoot == NULL)
            return true;
        if (pRoot->_pLeft == NULL&&pRoot->_pRight == NULL)
            return true;
        int Left = _Height(pRoot->_pLeft);
        int Right = _Height(pRoot->_pRight);
        return abs(Left - Right) < 1;
    }

求树的高度
代码实现如下所示:

size_t _Height(pNode pRoot)
    {
        if (NULL == pRoot)
            return 0;

        if (NULL == pRoot->_pLeft&&NULL == pRoot->_pRight)
            return 1;

        size_t left = _Height(pRoot->_pLeft);
        size_t right = _Height(pRoot->_pRight);
        return left >= right ? left + 1 : right + 1;
    }

测试代码如下所示:

void TestTree()
{
    //利用数组
    char array[] = "abd###ce##f";
    BindaryTree<char> bt(array, strlen(array), '#');
    cout << "非空树1(多个结点)---->" ;
    if (bt.IsBalanceTree())
        cout << "平衡" << endl;
    else
        cout << "不平衡" << endl;

    cout << "非空树2(多个结点)---->" ;
    char array1[] = "abd##c";
    BindaryTree<char> bt1(array1, strlen(array1), '#');
    if (bt1.IsBalanceTree())
        cout << "平衡" << endl;
    else
        cout << "不平衡" << endl;

    char array2[] = "a";
    BindaryTree<char> bt2(array2, strlen(array2), '#');
    cout << "非空树3(只有一个结点)---->" ;
    if (bt2.IsBalanceTree())
        cout << "平衡" << endl;
    else
        cout << "不平衡" << endl;

    //空树
    cout << "空树---->";
    BindaryTree<char> bt3;
    if (bt3.IsBalanceTree())
        cout << "平衡" << endl;
    else
        cout << "不平衡" << endl;
}

二叉树的面试题之判断树

有关树的判断,就这么多了,还请大家多多关照!!!
只有不停的奔跑,才能不停留在原地!!!