順序存儲空間利用率低,二叉樹通常採用二叉鏈表:每個節點包含數據域 data、左指針 lchild、右指針 rchild。若再加父指針則為三叉鏈表。
private static class Node {
Integer data;
Node lchild, rchild;
}

輸入先序序列,空節點用 0 表示(如 1,2,3,4,0,5,7,8)。利用完全二叉樹性質:索引 i 的左子節點為 2i,右子節點為 2i+1,遞歸構建。
public Node build(int index) {
if (index > n) return null;
Integer val = nodes[index - 1];
if (val == 0) return null;
Node node = new Node();
node.data = val;
node.lchild = build(2 * index);
node.rchild = build(2 * index + 1);
return node;
}
借助隊列,先入根節點,循環出隊訪問,將非空左右子節點入隊。
public void levelOrder(Node root) {
Queue q = new LinkedList<>();
q.offer(root);
while (!q.isEmpty()) {
Node cur = q.poll();
System.out.print(cur.data + " ");
if (cur.lchild != null) q.offer(cur.lchild);
if (cur.rchild != null) q.offer(cur.rchild);
}
}
public void preOrderRecur(Node node) {
if (node == null) return;
System.out.print(node.data + " ");
preOrderRecur(node.lchild);
preOrderRecur(node.rchild);
}
方法一:先壓右再壓左,保證左子樹先出棧。
public void preOrder(Node root) {
Stack st = new Stack<>();
st.push(root);
while (!st.isEmpty()) {
Node cur = st.pop();
System.out.print(cur.data + " ");
if (cur.rchild != null) st.push(cur.rchild);
if (cur.lchild != null) st.push(cur.lchild);
}
}
方法二:沿左鏈入棧,彈出後轉向右子樹。
public void preOrderOne(Node root) {
Stack st = new Stack<>();
Node cur = root;
while (cur != null || !st.isEmpty()) {
while (cur != null) {
System.out.print(cur.data + " ");
st.push(cur);
cur = cur.lchild;
}
cur = st.pop().rchild;
}
}
public void inOrderRecur(Node node) {
if (node == null) return;
inOrderRecur(node.lchild);
System.out.print(node.data + " ");
inOrderRecur(node.rchild);
}
public void inOrder(Node root) {
Stack st = new Stack<>();
Node cur = root;
while (cur != null || !st.isEmpty()) {
while (cur != null) {
st.push(cur);
cur = cur.lchild;
}
cur = st.pop();
System.out.print(cur.data + " ");
cur = cur.rchild;
}
}
public void postOrderRecur(Node node) {
if (node == null) return;
postOrderRecur(node.lchild);
postOrderRecur(node.rchild);
System.out.print(node.data + " ");
}
public void postOrder(Node root) {
Stack st = new Stack<>();
Node pre = null; // 記錄上一次訪問的節點
Node cur = root;
while (cur != null || !st.isEmpty()) {
while (cur != null) {
st.push(cur);
cur = cur.lchild;
}
Node top = st.peek();
// 若右子樹為空或已訪問過,則訪問當前節點
if (top.rchild == null || pre == top.rchild) {
System.out.print(top.data + " ");
pre = st.pop();
} else {
cur = top.rchild;
}
}
}
輸入序列 1,2,3,4,0,5,7,8 對應樹結構:
1
/ \
2 3
/ / \
4 5 7
\
8
運行結果:
先序遍歷(遞歸):1 2 4 3 5 8 7
中序遍歷(遞歸):4 2 1 5 8 3 7
後序遍歷(遞歸):4 2 8 5 7 3 1
層次遍歷:1 2 3 4 5 7 8
先序遍歷(非遞歸):1 2 4 3 5 8 7
中序遍歷(非遞歸):4 2 1 5 8 3 7
後序遍歷(非遞歸):4 2 8 5 7 3 1

pre 指針法)。