7.1 Binary trees¶
A binary tree is a nonlinear data structure representing relationships between ancestors and descendants. It embodies the divide-and-conquer idea of splitting in two. Like a linked list, it is built from nodes, each containing a value and references to its left and right children.
/* Binary tree node class */
class TreeNode {
val: number;
left: TreeNode | null;
right: TreeNode | null;
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
this.val = val === undefined ? 0 : val; // Node value
this.left = left === undefined ? null : left; // Left child reference
this.right = right === undefined ? null : right; // Right child reference
}
}
use std::rc::Rc;
use std::cell::RefCell;
/* Binary tree node struct */
struct TreeNode {
val: i32, // Node value
left: Option<Rc<RefCell<TreeNode>>>, // Left child reference
right: Option<Rc<RefCell<TreeNode>>>, // Right child reference
}
impl TreeNode {
/* Constructor */
fn new(val: i32) -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Self {
val,
left: None,
right: None
}))
}
}
/* Binary tree node struct */
typedef struct TreeNode {
int val; // Node value
int height; // Node height
struct TreeNode *left; // Left child pointer
struct TreeNode *right; // Right child pointer
} TreeNode;
/* Constructor */
TreeNode *newTreeNode(int val) {
TreeNode *node;
node = (TreeNode *)malloc(sizeof(TreeNode));
node->val = val;
node->height = 0;
node->left = NULL;
node->right = NULL;
return node;
}
Each node has two references or pointers, one to its left child and one to its right child. The node is their parent. Its left child and all nodes below that child form its left subtree; the right subtree is defined similarly.
Every non-leaf node has children and at least one nonempty subtree. In Figure 7-1, if node 2 is the parent, its left and right children are nodes 4 and 5. Its left subtree consists of node 4 and everything below it, and its right subtree consists of node 5 and everything below it.

Figure 7-1 Parents, children, and subtrees
7.1.1 Common terminology¶
Figure 7-2 illustrates common binary-tree terminology.
- Root: the topmost node, which has no parent.
- Leaf: a node with no children; both of its child references point to
None. - Edge: a connection between two nodes, represented by a reference or pointer.
- A node's level: levels increase from top to bottom, with the root at level 1.
- A node's degree: its number of children, which is 0, 1, or 2 in a binary tree.
- A tree's height: the number of edges from the root to its farthest leaf.
- A node's depth: the number of edges from the root to that node.
- A node's height: the number of edges from that node to its farthest leaf.

Figure 7-2 Common binary-tree terminology
Tip
Height and depth are usually measured in edges, but some problems or textbooks count nodes instead. Under that convention, add 1 to both height and depth.
7.1.2 Basic operations¶
1. Initializing a binary tree¶
As with a linked list, first create the nodes, then connect them with references or pointers.
/* Initialize a binary tree */
// Initialize nodes
TreeNode* n1 = new TreeNode(1);
TreeNode* n2 = new TreeNode(2);
TreeNode* n3 = new TreeNode(3);
TreeNode* n4 = new TreeNode(4);
TreeNode* n5 = new TreeNode(5);
// Connect nodes with references (pointers)
n1->left = n2;
n1->right = n3;
n2->left = n4;
n2->right = n5;
/* Initialize a binary tree */
// Initialize nodes
TreeNode n1 = new TreeNode(1);
TreeNode n2 = new TreeNode(2);
TreeNode n3 = new TreeNode(3);
TreeNode n4 = new TreeNode(4);
TreeNode n5 = new TreeNode(5);
// Connect nodes with references (pointers)
n1.left = n2;
n1.right = n3;
n2.left = n4;
n2.right = n5;
// Initialize nodes
let n1 = TreeNode::new(1);
let n2 = TreeNode::new(2);
let n3 = TreeNode::new(3);
let n4 = TreeNode::new(4);
let n5 = TreeNode::new(5);
// Connect nodes with references (pointers)
n1.borrow_mut().left = Some(n2.clone());
n1.borrow_mut().right = Some(n3);
n2.borrow_mut().left = Some(n4);
n2.borrow_mut().right = Some(n5);
/* Initialize a binary tree */
// Initialize nodes
TreeNode *n1 = newTreeNode(1);
TreeNode *n2 = newTreeNode(2);
TreeNode *n3 = newTreeNode(3);
TreeNode *n4 = newTreeNode(4);
TreeNode *n5 = newTreeNode(5);
// Connect nodes with references (pointers)
n1->left = n2;
n1->right = n3;
n2->left = n4;
n2->right = n5;
Visualize execution
2. Inserting and deleting nodes¶
As with linked lists, insertion and deletion can be implemented by changing pointers. An example is shown below.

Figure 7-3 Inserting and deleting a binary-tree node
Visualize execution
Tip
Inserting a node may change the tree's logical structure, while deleting a node generally means deleting it and all its subtrees. Meaningful insertion and deletion operations therefore usually require several coordinated steps.
7.1.3 Common types of binary trees¶
1. Perfect binary trees¶
In a perfect binary tree, every level is completely filled, as shown below. Leaves have degree \(0\), and all other nodes have degree \(2\). A tree of height \(h\) has \(2^{h+1} - 1\) nodes, an exponential relationship reminiscent of cell division in nature.
Tip
In Chinese-language resources, a perfect binary tree is often called 满二叉树.

Figure 7-4 A perfect binary tree
2. Complete binary trees¶
Only the lowest level of a complete binary tree may be incomplete, and its nodes must fill that level consecutively from left to right, as shown below. Every perfect binary tree is also complete.

Figure 7-5 A complete binary tree
3. Full binary trees¶
In a full binary tree, every node other than a leaf has exactly two children, as shown below.

Figure 7-6 A full binary tree
4. Balanced binary trees¶
In a balanced binary tree, the heights of the left and right subtrees of every node differ by at most 1, as shown below.

Figure 7-7 A balanced binary tree
7.1.4 Degeneration of a binary tree¶
Figure 7-8 shows ideal and degenerate tree structures. When every level is full, the tree is perfect. When every node lies along one side, the tree degenerates into a linked list.
- A perfect binary tree is the ideal case, making full use of divide and conquer.
- A linked list is the opposite extreme: operations become linear, with time complexity degrading to \(O(n)\).

Figure 7-8 Best and worst binary-tree structures
As Table 7-1 shows, quantities such as leaf count, total node count, and height reach their maximum or minimum values in these best and worst structures.
Table 7-1 Best and worst binary-tree structures
| Perfect binary tree | Linked list | |
|---|---|---|
| Nodes at level \(i\) | \(2^{i-1}\) | \(1\) |
| Leaves in a tree of height \(h\) | \(2^h\) | \(1\) |
| Total nodes in a tree of height \(h\) | \(2^{h+1} - 1\) | \(h + 1\) |
| Height of a tree with \(n\) nodes | \(\log_2 (n+1) - 1\) | \(n - 1\) |