二叉树实战(二) - 二叉树的遍历方式
二叉树的遍历方式分为三种, 根据根节点的访问时机,定义以下三种方式:
1). 前序遍历
先访问跟结点,再访问左子树,最后访问右子树。
2). 中序遍历
先访问左子树,再访问根结点,最后访问右子树。
3). 后序遍历
先访问左子树,再访问右子树,最后访问根结点。
在二叉查找树的代码基础上实现遍历以上遍历功能:
import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; /** * 二叉查找树遍历 * * @param <Key> * @param <Value> */ public class BinaryTreeErgodic<Key extends Comparable<Key>, Value> { public static void main(String[] args) { BinaryTreeErgodic<String, String> tree = new BinaryTreeErgodic<>(); tree.put("E", "5"); tree.put("B", "2"); tree.put("G", "7"); tree.put("A", "1"); tree.put("D", "4"); tree.put("F", "6"); tree.put("H", "8"); tree.put("C", "3"); //Queue<String> keys = tree.preErgodic(); //System.out.println(keys.toString()); //Queue<String> keys = tree.midErgodic(); //System.out.println(keys.toString()); Queue<String> keys = tree.afterErgodic(); System.out.println(keys.toString()); } /******************************************** * 二叉查找树,实现核心功能 * 1.插入 * 2.查找 * 3.删除 * 4.查询最小值 * 5.查询最大值 * * 遍历方式: * 1.前序遍历 * 2.中序遍历 * 3.后序遍历 ********************************************/ // 记录根节点 private Node root; // 记录树中元素的个数 private int N; /** * 树节点结构体类 */ private class Node { public Key key; // 存储键 public Value value; // 存储值 public Node left; // 记录左子节点 public Node right; // 记录右子节点 public Node(Key key, Value value, Node left, Node right) { this.key = key; this.value = value; this.left = left; this.right = right; } } // 获取树中元素的个数 public int getSize() { return N; } // 向树中添加元素 key-value public void put(Key key, Value value) { root = put(root, key, value); } // 向指定的树x中添加key-value,并返回添加元素后的新树 private Node put(Node x, Key key, Value value) { // 如果x的子树为空 if (x == null) { N++; return new Node(key, value, null, null); } // 如果x的子树不为空,则比较x节点的键和key的大小 // 如果key小于x结点的键,则继续找x结点的左子树。如果key大于x结点的键,则继续找x结点的右子树,如果key等于x结点的键,则替换x结点的值为value即可。 int cmp = key.compareTo(x.key); if (cmp > 0) { x.right = put(x.right, key, value); } else if (cmp < 0) { x.left = put(x.left, key, value); } else { x.value = value; } return x; } // 查询树中指定的key对应的value public Value get(Key key) { return get(root, key); } // 从指定的树x中,查找key对应的值 private Value get(Node x, Key key) { // x树为NULL if (x == null) { return null; } // x树不为NULL,比较键的大小 // 如果key小于x结点的键,则继续找x结点的左子树。如果key大于x结点的键,则继续找x结点的右子树,如果key等于x结点的键,则返回该键的值 int cmp = key.compareTo(x.key); if (cmp > 0) { return get(x.right, key); } else if (cmp < 0) { return get(x.left, key); } else { return x.value; } } // 删除树中key对应的value public void delete(Key key) { delete(root, key); } // 删除指定树x中key对应的value,并返回删除后的新树 private Node delete(Node x, Key key) { // x树为null if (x == null) { return null; } // x树不为NULL,比较键的大小 // 如果key小于x结点的键,则继续找x结点的左子树。如果key大于x结点的键,则继续找x结点的右子树,如果key等于x结点的键,执行真正的删除操作 int cmp = key.compareTo(x.key); if (cmp > 0) { return x.right = delete(x.right, key); } else if (cmp < 0) { return x.left = delete(x.left, key); } else { N--; if (x.right == null) { return x.left; } if (x.left == null) { return x.right; } // 找到右子树的最小结点 Node minNode = x.right; while (minNode.left != null) { minNode = minNode.left; } // 删除右子树中最小的结点 Node n = x.right; while (n.left != null) { if (n.left.left == null) { n.left = null; } else { n = n.left; // 变换n结点 } } // 让x结点的左子树成为minNode的左子树 minNode.left = x.left; // 让x结点的右子树成为minNode的右子树 minNode.right = x.right; // 让x结点的父结点指向minNode x = minNode; return x; } } // 找出整个树中最小的键 public Key getMin() { return min(root).key; } // 找到指定树x中最小值的键所在的结点 private Node min(Node x) { if (x.left != null) { return min(x.left); } else { return x; } } // 找出整个树中最大的键 public Key getMax() { return max(root).key; } // 找到指定树x中最大值的键所在的结点 private Node max(Node x) { if (x.right != null) { return max(x.right); } else { return x; } } // 获取整个树中所有的键(采用先序遍历) public Queue<Key> preErgodic() { Queue<Key> keys = new ConcurrentLinkedQueue<>(); preErgodic(root, keys); return keys; } private void preErgodic(Node x, Queue<Key> keys) { if (x == null) { return; } // 把x结点的key放入到keys中 keys.offer(x.key); // 递归遍历x结点的左子树 if (x.left != null) { preErgodic(x.left, keys); } // 递归遍历x结点的右子树 if (x.right != null) { preErgodic(x.right, keys); } } // 获取整个树中所有的键(采用先序遍历) public Queue<Key> midErgodic() { Queue<Key> keys = new ConcurrentLinkedQueue<>(); midErgodic(root, keys); return keys; } private void midErgodic(Node x, Queue<Key> keys) { if (x == null) { return; } // 递归遍历x结点的左子树 if (x.left != null) { midErgodic(x.left, keys); } // 把x结点的key放入到keys中 keys.offer(x.key); // 递归遍历x结点的右子树 if (x.right != null) { midErgodic(x.right, keys); } } // 获取整个树中所有的键(采用先序遍历) public Queue<Key> afterErgodic() { Queue<Key> keys = new ConcurrentLinkedQueue<>(); afterErgodic(root, keys); return keys; } private void afterErgodic(Node x, Queue<Key> keys) { if (x == null) { return; } // 递归遍历x结点的左子树 if (x.left != null) { afterErgodic(x.left, keys); } // 递归遍历x结点的右子树 if (x.right != null) { afterErgodic(x.right, keys); } // 把x结点的key放入到keys中 keys.offer(x.key); } }

浙公网安备 33010602011771号