複製鏈接
請複製以下鏈接發送給好友

完全二叉樹

鎖定
一棵深度為k的有n個結點的二叉樹,對樹中的結點按從上至下、從左到右的順序進行編號,如果編號為i(1≤i≤n)的結點與滿二叉樹中編號為i的結點在二叉樹中的位置相同,則這棵二叉樹稱為完全二叉樹。 [1] 
中文名
完全二叉樹
外文名
Complete Binary Tree [1] 
實    質
效率很高的數據結構 [1] 
特    點
葉子結點只可能在最大的兩層出現 [1] 
應用學科
計算機科學 [1] 

完全二叉樹定義

一棵深度為k且有
個結點的二叉樹稱為滿二叉樹。 [2] 
根據二叉樹的性質2, 滿二叉樹每一層的結點個數都達到了最大值, 即滿二叉樹的第i層上有
個結點 (i≥1) 。 [2] 
如果對滿二叉樹的結點進行編號, 約定編號從根結點起, 自上而下, 自左而右。則深度為k的, 有n個結點的二叉樹, 當且僅當其每一個結點都與深度為k的滿二叉樹中編號從1至n的結點一一對應時, 稱之為完全二叉樹。 [2] 
滿二叉樹和完全二叉樹的定義可以看出, 滿二叉樹是完全二叉樹的特殊形態, 即如果一棵二叉樹是滿二叉樹, 則它必定是完全二叉樹。 [2] 
完全二叉樹 完全二叉樹 [2]

完全二叉樹性質

1、具有n個結點的完全二叉樹的深度
(注:[ ]表示向下取整) [4] 
2、如果對一棵有n個結點的完全二叉樹的結點按層序編號, 則對任一結點i (1≤i≤n) 有: [2] 
  • 如果i=1, 則結點i是二叉樹的根, 無雙親;如果i>1, 則其雙親parent (i) 是結點[i/2]. [2] 
  • 如果2i>n, 則結點i無左孩子, 否則其左孩子lchild (i) 是結點2i; [2] 
  • 如果2i+1>n, 則結點i無右孩子, 否則其右孩子rchild (i) 是結點2i+1. [2] 

完全二叉樹特點

完全二叉樹的特點:葉子結點只能出現在最下層和次下層,且最下層的葉子結點集中在樹的左部。需要注意的是,滿二叉樹肯定是完全二叉樹,而完全二叉樹不一定是滿二叉樹。 [1] 

完全二叉樹完全二叉樹判定

完全二叉樹算法思路

判斷一棵樹是否是完全二叉樹的思路 [3] 
1>如果樹為空,則直接返回錯
2>如果樹不為空:層序遍歷二叉樹
2.1>如果一個結點左右孩子都不為空,則pop該節點,將其左右孩子入隊列;
2.1>如果遇到一個結點,左孩子為空,右孩子不為空,則該樹一定不是完全二叉樹;
2.2>如果遇到一個結點,左孩子不為空,右孩子為空;或者左右孩子都為空,且則該節點之後的隊列中的結點都為葉子節點,該樹才是完全二叉樹,否則就不是完全二叉樹; [3] 

完全二叉樹代碼實現

#include <iostream>
#include <queue>

using namespace std;

template <class T>
struct TreeNode
{
    T data;
    TreeNode<T> *left;
    TreeNode<T> *right;
    TreeNode(const T &x) : data(x),
                           left(NULL),
                           right(NULL) {}
};
template <class T>
bool IsComplete(TreeNode<T> *root)
{
    //1.樹為空,返回錯誤
    if (root == NULL)
    {
        return false;
    }
    //2.樹不為空
    queue<TreeNode<T> *> q;
    q.push(root);
    while (!q.empty())
    {
        TreeNode<T> *top = q.front();
        //2.1如果該節點兩個孩子都有,則直接pop
        if (top->left && top->right)
        {
            q.pop();
            q.push(top->left);
            q.push(top->right);
        }
        //2.2如果該節點左孩子為空,右孩子不為空,則一定不是完全二叉樹
        if (top->left == NULL && top->right)
        {
            return false;
        }
        //2.3如果該節點左孩子不為空,右孩子為空或者該節點為葉子節點,則該節點之後的所有結點都是葉子節點
        if ((top->left && top->right == NULL) || (top->left == NULL && top->right == NULL))
        {
                        if (NULL != top->left && NULL == top->right) 
                        {
                            q.push(top->left);    
                        }
            q.pop(); //則該節點之後的所有結點都是葉子節點
            while (!q.empty())
            {
                top = q.front();
                if (top->left == NULL && top->right == NULL)
                {
                    q.pop();
                }
                else
                {
                    return false;
                }
            }
            return true;
        }
    }
    return true;
}

//滿二叉樹
void test1()
{
    //       1
    //   2       3
    // 4    5  6   7
    TreeNode<int> *node1 = new TreeNode<int>(1);
    TreeNode<int> *node2 = new TreeNode<int>(2);
    TreeNode<int> *node3 = new TreeNode<int>(3);
    TreeNode<int> *node4 = new TreeNode<int>(4);
    TreeNode<int> *node5 = new TreeNode<int>(5);
    TreeNode<int> *node6 = new TreeNode<int>(6);
    TreeNode<int> *node7 = new TreeNode<int>(7);
    node1->left = node2;
    node1->right = node3;
    node2->left = node4;
    node2->right = node5;
    node3->left = node6;
    node3->right = node7;
    cout << IsComplete<int>(node1) << endl;
}

//二叉樹為空
void test2()
{
    cout << IsComplete<int>(NULL) << endl;
}

//3.二叉樹不為空,也不是滿二叉樹,遇到一個結點左孩子為空,右孩子不為空
void test3()
{
    //       1
    //   2       3
    // 4    5      7
    TreeNode<int> *node1 = new TreeNode<int>(1);
    TreeNode<int> *node2 = new TreeNode<int>(2);
    TreeNode<int> *node3 = new TreeNode<int>(3);
    TreeNode<int> *node4 = new TreeNode<int>(4);
    TreeNode<int> *node5 = new TreeNode<int>(5);
    TreeNode<int> *node7 = new TreeNode<int>(7);
    node1->left = node2;
    node1->right = node3;
    node2->left = node4;
    node2->right = node5;
    node3->right = node7;
    cout << IsComplete<int>(node1) << endl;
}

//4.二叉樹不為空,也不是滿二叉樹,遇到葉子節點,則該葉子節點之後的所有結點都為葉子節點
void test4()
{
    //        1
    //    2       3
    // 4    5
    TreeNode<int> *node1 = new TreeNode<int>(1);
    TreeNode<int> *node2 = new TreeNode<int>(2);
    TreeNode<int> *node3 = new TreeNode<int>(3);
    TreeNode<int> *node4 = new TreeNode<int>(4);
    TreeNode<int> *node5 = new TreeNode<int>(5);
    node1->left = node2;
    node1->right = node3;
    node2->left = node4;
    node2->right = node5;
    cout << IsComplete<int>(node1) << endl;
}

//4.二叉樹不為空,也不是滿二叉樹,遇到左孩子不為空,右孩子為空的結點,則該節點之後的所有結點都為葉子節點
void test5()
{
    //        1
    //    2       3
    // 4    5   6
    TreeNode<int> *node1 = new TreeNode<int>(1);
    TreeNode<int> *node2 = new TreeNode<int>(2);
    TreeNode<int> *node3 = new TreeNode<int>(3);
    TreeNode<int> *node4 = new TreeNode<int>(4);
    TreeNode<int> *node5 = new TreeNode<int>(5);
    TreeNode<int> *node6 = new TreeNode<int>(6);
    node1->left = node2;
    node1->right = node3;
    node2->left = node4;
    node2->right = node5;
    node3->left = node6;
    cout << IsComplete<int>(node1) << endl;
}

int main()
{
    test1();
    /*test2();*/
    /*test3();*/
    /*test4();*/
    /*test5();*/
    return 0;
}

參考資料