Trees came out of graph theory. This concept allows us to make concrete data structures that allow us to implement the tree structure.
One way we could do this:
struct Node {
T datum;
Node *left, *right;
};
This is efficient for moving down a tree from parent to child. No easy way to go backwards.
A tree is a set of nodes for storing elements in a parent-child relationship.
Binary tree: every node has at most two children
Depth of root is 0, depth of node is depth of parent + 1.
A proper binary tree is a tree where all external nodes have zero children, and each internal node have two children.
A complete binary tree is a tree where every level is full except the last level, which is filled from left to right.
Array-based binary tree implementation:
Complexity of array implementation:
Complexity of node-based implementation:
You can improve the parent operation by introducing a parent pointer. However, this is not that common because while it might make things easier to use parent pointers, there is nothing you can do with parent pointers that you couldn't do without them.
Start at the root node. Of its multitude of siblings, the first sibling becomes the left child of a, and c and d become children of b. C has children e and f, etc. Basically, you go through and each two elements become children of the new nodes.
Algorithm preorder(T, v)
visit node v
for (node c : v.children())
preorder(T, c)
Algorithm inorder(T, v)
inorder(T, leftchild(v))
visit node v
inorder(T, rightchild(v))
Algorithm postorder(T, v)
for (node c : v.children())
postorder(T, c)
visit node v