Both general and binary trees can be implemented using a linked list type of data structure.
/** An example general tree node */
class Node<T> {
T value;
Node<T> parent;
List<Node<T>> children;
Node(T value, Node<T> parent) {
this.value = value;
this.parent = parent;
this.children = new ArrayList<>();
}
void addChild(Node<T> child) {
child.parent = this;
this.children.add(child);
}
Node<T> addChild(T value) {
Node<T> child = new Node<>(value, this);
this.children.add(child);
return child;
}
}
Computing height and depth for linked listed based versions.
/** Return depth of given node. */
int depth(Node<T> node) {
if (node == null)
throw new IllegalArgumentException("Node is not in tree");
if (node == isRoot(node))
return 0;
return 1 + depth(node.parent);
}
/** Return the height from given node */
int height(Node<T> node) {
int ht = 0;
for (Node<T> child: node.children) {
ht = Math.max(ht, 1 + height(child));
}
return ht;
}
Binary trees can also be implemented using arrays. See min/max heap implementation.
class BinaryTree<T> {
List<T> values = new ArrayList<>();
void add(T value) {
values.add(value);
}
T getParent(int i) {
if (i == 0) return null;
int p = (i - 1) / 2;
return values.get(p);
}
T getLeft(int i) {
int l = (i * 2) + 1;
if (l >= values.size()) return null;
return values.get(l);
}
T getRight(int i) {
int r = (i * 2) + 2;
if (r >= values.size()) return null;
return values.get(r);
}
}
The search tree is deepened as much as possible before going to the next sibling.
PreOrder Traversal
void generalPreOrder(Node<T> node) {
// Perform visit of node
// Next visit children of node
for (Node<T> child: node.children)
generalPreOrder(child);
}
PostOrder Traversal
void generalPostOrder(Node<T> node) {
// Visit all children first
for (Node<T> child: node.children)
generalPostOrder(child);
// Perform visit of node
}
InOrder Traversal
void binaryInOrder(Node<T> node) {
if (node == null)
return;
binaryInOrder(node.left);
// Perform visit to node
binaryInOrder(node.right);
}
The search tree is broadened as much as possible before going to the next depth.
void bfs(Node<T> node) {
Queue<Node<T>> queue = new Queue<>();
queue.enqueue(node);
while (!queue.isEmpty()) {
Node<T> curr = queue.dequeue();
// Perform visit of current node
for (Node<T> child: curr.children)
queue.enqueue(child);
}
}