数据结构——二叉树的最大宽度

原文地址:Maximum width of a binary tree

已知一个二叉树,写一个函数得到已知二叉树的最大宽度。一个树的宽度指的是所有层的宽度的最大值。

我们想一下下面的例子:

         1
        /  \
       2    3
     /  \     \
    4    5     8 
              /  \
             6    7

对于上面这个树:

第一层的宽度是1,
第二层的宽度是2,
第三层的宽度是3,
第四层的宽度是2。

所以树的宽度是3。

方法1(用层级遍历)

这个方法主要有两个函数。一个是计数一个已知层的节点的数目(getWidth),另一个是得到树的最大宽度(getMaxWidth)。getMaxWidth()利用getWidth()得到从根开始的所有层的宽度。

/*Function to print level order traversal of tree*/
getMaxWidth(tree)
maxWdth = 0
for i = 1 to height(tree)
  width =   getWidth(tree, i);
  if(width > maxWdth) 
      maxWdth  = width
return width
/*Function to get width of a given level */
getWidth(tree, level)
if tree is NULL then return 0;
if level is 1, then return 1;  
else if level greater than 1, then
    return getWidth(tree->left, level-1) + 
    getWidth(tree->right, level-1);
// Java program to calculate width of binary tree

/* A binary tree node has data, pointer to left child
   and a pointer to right child */
class Node 
{
    int data;
    Node left, right;

    Node(int item) 
    {
        data = item;
        left = right = null;
    }
}

class BinaryTree 
{
    Node root;

    /* Function to get the maximum width of a binary tree*/
    int getMaxWidth(Node node) 
    {
        int maxWidth = 0;
        int width;
        int h = height(node);
        int i;

        /* Get width of each level and compare 
           the width with maximum width so far */
        for (i = 1; i <= h; i++) 
        {
            width = getWidth(node, i);
            if (width > maxWidth)
                maxWidth = width;
        }

        return maxWidth;
    }

    /* Get width of a given level */
    int getWidth(Node node, int level) 
    {
        if (node == null)
            return 0;

        if (level == 1)
            return 1;
        else if (level > 1)
            return getWidth(node.left, level - 1)
                    + getWidth(node.right, level - 1);
        return 0;
    }

    /* UTILITY FUNCTIONS */

    /* Compute the "height" of a tree -- the number of
     nodes along the longest path from the root node
     down to the farthest leaf node.*/
    int height(Node node) 
    {
        if (node == null)
            return 0;
        else
        {
            /* compute the height of each subtree */
            int lHeight = height(node.left);
            int rHeight = height(node.right);

            /* use the larger one */
            return (lHeight > rHeight) ? (lHeight + 1) : (rHeight + 1);
        }
    }

    /* Driver program to test above functions */
    public static void main(String args[]) 
    {
        BinaryTree tree = new BinaryTree();

        /*
        Constructed bunary tree is:
              1
            /  \
           2    3
         /  \    \
        4   5     8 
                 /  \
                6   7
         */
        tree.root = new Node(1);
        tree.root.left = new Node(2);
        tree.root.right = new Node(3);
        tree.root.left.left = new Node(4);
        tree.root.left.right = new Node(5);
        tree.root.right.right = new Node(8);
        tree.root.right.right.left = new Node(6);
        tree.root.right.right.right = new Node(7);

        System.out.println("Maximum width is " + tree.getMaxWidth(tree.root));
    }
}

// This code has been contributed by Mayank Jaiswal

时间复杂度:最差情况下是 O(n2)

我们可以用队列基于层级遍历来优化这个方法的时间复杂度。基于层级顺序的队列在最坏的情况下花费O(n)。

方法2(用队列做层级遍历)

在这个方法中,我们在队列中保存了当前层的所有孩子节点,然后在指定层的层级遍历完成之后计算这一层节点的个数。因为队列现在保存了下一层的所有节点,所以我们用队列的大小很容易地得到下一层节点的总数。然后我们根据相同的过程处理下一层。我们存储并更新每一层找到的节点最大数目。

// A queue based C++ program to find maximum width
// of a Binary Tree
#include<bits/stdc++.h>
using namespace std ;

/* A binary tree node has data, pointer to left child
   and a pointer to right child */
struct Node
{
    int data ;
    struct Node * left ;
    struct Node * right ;
};

// Function to find the maximum width of the tree
// using level order traversal
int maxWidth(struct Node * root)
{
    // Base case
    if (root == NULL)
        return 0;

    // Initialize result
    int result = 0;

    // Do Level order traversal keeping track of number
    // of nodes at every level.
    queue<Node*> q;
    q.push(root);
    while (!q.empty())
    {
        // Get the size of queue when the level order
        // traversal for one level finishes
        int count = q.size() ;

        // Update the maximum node count value
        result = max(count, result);

        // Iterate for all the nodes in the queue currently
        while (count--)
        {
            // Dequeue an node from queue
            Node *temp = q.front();
            q.pop();

            // Enqueue left and right children of
            // dequeued node
            if (temp->left != NULL)
                q.push(temp->left);
            if (temp->right != NULL)
                q.push(temp->right);
        }
    }

    return result;
}

/* Helper function that allocates a new node with the
   given data and NULL left and right pointers. */
struct Node * newNode(int data)
{
    struct Node * node = new Node;
    node->data = data;
    node->left = node->right = NULL;
    return (node);
}

int main()
{
    struct Node *root = newNode(1);
    root->left        = newNode(2);
    root->right       = newNode(3);
    root->left->left  = newNode(4);
    root->left->right = newNode(5);
    root->right->right = newNode(8);
    root->right->right->left  = newNode(6);
    root->right->right->right  = newNode(7);

    /*   Constructed Binary tree is:
                 1
               /   \
             2      3
           /  \      \
          4    5      8
                    /   \
                   6     7    */
    cout << "Maximum width is "
         << maxWidth(root) << endl;
    return 0;
}

// This code is contributed by Nikhil Kumar Singh(nickzuck_007)

方法3(用先序遍历)

在这个方法中,我们建立一个临时数组count[],大小等于树的高度。我们初始化count中所有的值为0,用先序遍历遍历这个树,并填充count,这样二叉树的每一层的节点数目就包含在了count数组中。

// Java program to calculate width of binary tree

/* A binary tree node has data, pointer to left child
   and a pointer to right child */
class Node 
{
    int data;
    Node left, right;

    Node(int item) 
    {
        data = item;
        left = right = null;
    }
}

class BinaryTree 
{
    Node root;

    /* Function to get the maximum width of a binary tree*/
    int getMaxWidth(Node node) 
    {
        int width;
        int h = height(node);

        // Create an array that will store count of nodes at each level
        int count[] = new int[10];

        int level = 0;

        // Fill the count array using preorder traversal
        getMaxWidthRecur(node, count, level);

        // Return the maximum value from count array
        return getMax(count, h);
    }

    // A function that fills count array with count of nodes at every
    // level of given binary tree
    void getMaxWidthRecur(Node node, int count[], int level) 
    {
        if (node != null) 
        {
            count[level]++;
            getMaxWidthRecur(node.left, count, level + 1);
            getMaxWidthRecur(node.right, count, level + 1);
        }
    }

    /* UTILITY FUNCTIONS */

    /* Compute the "height" of a tree -- the number of
     nodes along the longest path from the root node
     down to the farthest leaf node.*/
    int height(Node node) 
    {
        if (node == null) 
            return 0;
        else
        {
            /* compute the height of each subtree */
            int lHeight = height(node.left);
            int rHeight = height(node.right);

            /* use the larger one */
            return (lHeight > rHeight) ? (lHeight + 1) : (rHeight + 1);
        }
    }

    // Return the maximum value from count array
    int getMax(int arr[], int n) 
    {
        int max = arr[0];
        int i;
        for (i = 0; i < n; i++) 
        {
            if (arr[i] > max)
                max = arr[i];
        }
        return max;
    }

    /* Driver program to test above functions */
    public static void main(String args[]) 
    {
        BinaryTree tree = new BinaryTree();

        /*
        Constructed bunary tree is:
              1
            /  \
           2    3
          / \    \
         4   5    8
                 / \
                6   7 */
        tree.root = new Node(1);
        tree.root.left = new Node(2);
        tree.root.right = new Node(3);
        tree.root.left.left = new Node(4);
        tree.root.left.right = new Node(5);
        tree.root.right.right = new Node(8);
        tree.root.right.right.left = new Node(6);
        tree.root.right.right.right = new Node(7);

        System.out.println("Maximum width is " + 
                           tree.getMaxWidth(tree.root));
    }
}

// This code has been contributed by Mayank Jaiswal

时间复杂度: O(n)

  • 10
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值