原文: https://www.programiz.com/dsa/complete-binary-tree

在本教程中,您将学习完全二叉树及其不同类型。 此外,您还将在 C,C++ ,Java 和 Python 中找到完全二叉树的工作示例。

完全二叉树是一棵二叉树,其中所有级别均已完全填充,但最低级别可能会从左侧填充。

完全二叉树就像满二叉树,但有两个主要区别

  1. 所有叶子元素都必须向左倾斜。
  2. 最后一个叶子元素可能没有正确的同级,即完全二叉树不必是满二叉树。

完全二叉树 - 图1

完全二叉树


完全二叉树 vs 满二叉树

完全二叉树 - 图2

完全二叉树与满二叉树的比较

完全二叉树 - 图3

完全二叉树与满二叉树的比较

完全二叉树 - 图4

完全二叉树与满二叉树的比较

完全二叉树 - 图5

完全二叉树与满二叉树的比较


如何创建完全二叉树?

  1. 选择列表的第一个元素作为根节点。 (级别 I 上的元素数:1)
    完全二叉树 - 图6
    选择第一个元素作为根

  2. 将第二个元素作为根节点的左子元素,将第三个元素作为右子元素。 (第 II 级元素的数量:2)
    完全二叉树 - 图7
    12 是左侧子级,9 是右侧子级

  3. 将接下来的两个元素作为第二级左节点的子级。 同样,将接下来的两个元素作为第二层右节点的子元素(第 III 层上的元素数量:4 个)。

  4. 不断重复,直到到达最后一个元素。
    完全二叉树 - 图8
    5 是左侧子级,6 是右侧子级


Python,Java 和 C/C++ 示例

  1. # Checking if a binary tree is a complete binary tree in C
  2. class Node:
  3. def __init__(self, item):
  4. self.item = item
  5. self.left = None
  6. self.right = None
  7. # Count the number of nodes
  8. def count_nodes(root):
  9. if root is None:
  10. return 0
  11. return (1 + count_nodes(root.left) + count_nodes(root.right))
  12. # Check if the tree is complete binary tree
  13. def is_complete(root, index, numberNodes):
  14. # Check if the tree is empty
  15. if root is None:
  16. return True
  17. if index >= numberNodes:
  18. return False
  19. return (is_complete(root.left, 2 * index + 1, numberNodes)
  20. and is_complete(root.right, 2 * index + 2, numberNodes))
  21. root = Node(1)
  22. root.left = Node(2)
  23. root.right = Node(3)
  24. root.left.left = Node(4)
  25. root.left.right = Node(5)
  26. root.right.left = Node(6)
  27. node_count = count_nodes(root)
  28. index = 0
  29. if is_complete(root, index, node_count):
  30. print("The tree is a complete binary tree")
  31. else:
  32. print("The tree is not a complete binary tree")
  1. // Checking if a binary tree is a complete binary tree in Java
  2. // Node creation
  3. class Node {
  4. int data;
  5. Node left, right;
  6. Node(int item) {
  7. data = item;
  8. left = right = null;
  9. }
  10. }
  11. class BinaryTree {
  12. Node root;
  13. // Count the number of nodes
  14. int countNumNodes(Node root) {
  15. if (root == null)
  16. return (0);
  17. return (1 + countNumNodes(root.left) + countNumNodes(root.right));
  18. }
  19. // Check for complete binary tree
  20. boolean checkComplete(Node root, int index, int numberNodes) {
  21. // Check if the tree is empty
  22. if (root == null)
  23. return true;
  24. if (index >= numberNodes)
  25. return false;
  26. return (checkComplete(root.left, 2 * index + 1, numberNodes)
  27. && checkComplete(root.right, 2 * index + 2, numberNodes));
  28. }
  29. public static void main(String args[]) {
  30. BinaryTree tree = new BinaryTree();
  31. tree.root = new Node(1);
  32. tree.root.left = new Node(2);
  33. tree.root.right = new Node(3);
  34. tree.root.left.right = new Node(5);
  35. tree.root.left.left = new Node(4);
  36. tree.root.right.left = new Node(6);
  37. int node_count = tree.countNumNodes(tree.root);
  38. int index = 0;
  39. if (tree.checkComplete(tree.root, index, node_count))
  40. System.out.println("The tree is a complete binary tree");
  41. else
  42. System.out.println("The tree is not a complete binary tree");
  43. }
  44. }
  1. // Checking if a binary tree is a complete binary tree in C
  2. #include <stdbool.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. struct Node {
  6. int key;
  7. struct Node *left, *right;
  8. };
  9. // Node creation
  10. struct Node *newNode(char k) {
  11. struct Node *node = (struct Node *)malloc(sizeof(struct Node));
  12. node->key = k;
  13. node->right = node->left = NULL;
  14. return node;
  15. }
  16. // Count the number of nodes
  17. int countNumNodes(struct Node *root) {
  18. if (root == NULL)
  19. return (0);
  20. return (1 + countNumNodes(root->left) + countNumNodes(root->right));
  21. }
  22. // Check if the tree is a complete binary tree
  23. bool checkComplete(struct Node *root, int index, int numberNodes) {
  24. // Check if the tree is complete
  25. if (root == NULL)
  26. return true;
  27. if (index >= numberNodes)
  28. return false;
  29. return (checkComplete(root->left, 2 * index + 1, numberNodes) && checkComplete(root->right, 2 * index + 2, numberNodes));
  30. }
  31. int main() {
  32. struct Node *root = NULL;
  33. root = newNode(1);
  34. root->left = newNode(2);
  35. root->right = newNode(3);
  36. root->left->left = newNode(4);
  37. root->left->right = newNode(5);
  38. root->right->left = newNode(6);
  39. int node_count = countNumNodes(root);
  40. int index = 0;
  41. if (checkComplete(root, index, node_count))
  42. printf("The tree is a complete binary tree\n");
  43. else
  44. printf("The tree is not a complete binary tree\n");
  45. }
  1. // Checking if a binary tree is a complete binary tree in C++
  2. #include <iostream>
  3. using namespace std;
  4. struct Node {
  5. int key;
  6. struct Node *left, *right;
  7. };
  8. // Create node
  9. struct Node *newNode(char k) {
  10. struct Node *node = (struct Node *)malloc(sizeof(struct Node));
  11. node->key = k;
  12. node->right = node->left = NULL;
  13. return node;
  14. }
  15. // Count the number of nodes
  16. int countNumNodes(struct Node *root) {
  17. if (root == NULL)
  18. return (0);
  19. return (1 + countNumNodes(root->left) + countNumNodes(root->right));
  20. }
  21. // Check if the tree is a complete binary tree
  22. bool checkComplete(struct Node *root, int index, int numberNodes) {
  23. // Check if the tree is empty
  24. if (root == NULL)
  25. return true;
  26. if (index >= numberNodes)
  27. return false;
  28. return (checkComplete(root->left, 2 * index + 1, numberNodes) && checkComplete(root->right, 2 * index + 2, numberNodes));
  29. }
  30. int main() {
  31. struct Node *root = NULL;
  32. root = newNode(1);
  33. root->left = newNode(2);
  34. root->right = newNode(3);
  35. root->left->left = newNode(4);
  36. root->left->right = newNode(5);
  37. root->right->left = newNode(6);
  38. int node_count = countNumNodes(root);
  39. int index = 0;
  40. if (checkComplete(root, index, node_count))
  41. cout << "The tree is a complete binary tree\n";
  42. else
  43. cout << "The tree is not a complete binary tree\n";
  44. }

数组索引和树元素之间的关系

完全二叉树具有一个有趣的属性,我们可以用来查找任何节点的子代和父代。

如果数组中任何元素的索引为i,则索引2i+1中的元素将成为左子元素,而2i+2索引中的元素将成为右子元素。 同样,索引为i的任何元素的父级都由(i-1)/2的下限给出。

让我们测试一下

  1. Left child of 1 (index 0)
  2. = element in (2*0+1) index
  3. = element in 1 index
  4. = 12
  5. Right child of 1
  6. = element in (2*0+2) index
  7. = element in 2 index
  8. = 9
  9. Similarly,
  10. Left child of 12 (index 1)
  11. = element in (2*1+1) index
  12. = element in 3 index
  13. = 5
  14. Right child of 12
  15. = element in (2*1+2) index
  16. = element in 4 index
  17. = 6

我们还要确认规则是否适用于寻找任何节点的父节点

  1. Parent of 9 (position 2)
  2. = (2-1)/2
  3. = ½
  4. = 0.5
  5. ~ 0 index
  6. = 1
  7. Parent of 12 (position 1)
  8. = (1-1)/2
  9. = 0 index
  10. = 1

了解数组索引到树位置的这种映射对于了解堆数据结构的工作方式以及如何用于实现堆排序至关重要。


完全二叉树应用