输入一颗二元查找树,将该树转换为它的镜像, 即在转换后的二元查找树中,左子树的结点都大于右子树的结点。 用递归和循环两种方法完成树的镜像转换。
递归遍历每个结点,然后转换左右结点。
前人写的二叉树java类,直接拿过来用。但是它的中序和后续的遍历代码调用了前序的代码,需要修改下。
/** * 二叉树的二叉链表表示 */ public class BinaryTree<T> { private TreeNode root; // 根节点 public BinaryTree() { } public BinaryTree(TreeNode root) { this.root = root; } /** * 定义节点 内部类 */ private static class TreeNode<T> { private T data = null; // 数据部分 private TreeNode lchild; // 左节点的引用 private TreeNode rchild; // 右节点的引用 protected TreeNode() { } protected TreeNode(T data, TreeNode lchild, TreeNode rchild) { this.data = data; this.lchild = lchild; this.rchild = rchild; } private T getData() { return data; } private void setData(T data) { this.data = data; } private TreeNode getLchild() { return lchild; } private void setLchild(TreeNode lchild) { this.lchild = lchild; } private TreeNode getRchild() { return rchild; } private void setRchild(TreeNode rchild) { this.rchild = rchild; } } /** * 返回父结点 * * @param element * @return */ public TreeNode getParent(TreeNode element) { // 如果传入参数为根节点或根节点为空,返回null return (root == null || root == element) ? null : parent(root, element); } /** * @param subTree * @param element * @return */ public TreeNode parent(TreeNode subTree, TreeNode element) { if (subTree == null) { return null; } // 如果subTree的左孩子节点或右孩子节点等于element,则返回subTree if (subTree.getLchild() == element || subTree.getRchild() == element) { // 返回父结点地址 return subTree; } TreeNode p; // 现在左子树中找,如果左子树中没有找到,才到右子树去找 if ((p = parent(subTree.getLchild(), element)) != null) { // 递归在左子树中搜索 return p; } else { // 递归在右子树中搜索 return parent(subTree.getRchild(), element); } } /** * 节点个数 * * @return */ public int getSize() { return getNum(root); } private int getNum(TreeNode node) { if (node == null) { return 0; } else { int i = getNum(node.getLchild()); int j = getNum(node.getRchild()); return j + i + 1; } } /** * 树高度 * * @return */ public int getHeight() { return getHeight(root); } private int getHeight(TreeNode tree) { if (tree == null) return 0;// 递归结束:空树高度为0 else { int i = getHeight(tree.getLchild()); int j = getHeight(tree.getRchild()); return (i < j) ? (j + 1) : (i + 1); } } /** * 前序遍历 先访问根结点,然后遍历左子树,最后遍历右子树 * * @param node */ public void preOrder(TreeNode node) { if (node != null) { System.out.println(node.getData()); preOrder(node.getLchild()); preOrder(node.getRchild()); } } /** * 中序遍历 首先遍历左子树,然后访问根结点,最后遍历右子树 * * @param node */ public void inOrder(TreeNode node) { if (node != null) { inOrder(node.getLchild()); System.out.println(node.getData()); inOrder(node.getRchild()); } } /** * 后序遍历 首先遍历左子树,然后遍历右子树,最后遍历访问根结点 * * @param node */ public void postOrder(TreeNode node) { if (node != null) { postOrder(node.getLchild()); postOrder(node.getRchild()); System.out.println(node.getData()); } } public static void main(String[] args) { TreeNode leaf1 = new TreeNode("5", null, null); // 没有左右孩子节点 TreeNode leaf2 = new TreeNode("7", null, null); // 没有左右孩子节点 TreeNode leaf3 = new TreeNode("9", null, null); // 没有左右孩子节点 TreeNode leaf4 = new TreeNode("11", null, null); // 没有左右孩子节点 TreeNode n3 = new TreeNode("6", leaf1, leaf2); // 根节点左子树 TreeNode n4 = new TreeNode("10", leaf3, leaf4); // 根节点右子树 TreeNode root = new TreeNode("8", n3, n4); // 创建根节点 BinaryTree bt = new BinaryTree(root); System.out.println("=======先序遍历======"); bt.preOrder(bt.root); System.out.println("=======中序遍历======"); bt.inOrder(bt.root); System.out.println("========后续遍历======="); bt.postOrder(bt.root); System.out.println("==========="); // System.out.println(bt.getHeight()); // System.out.println(bt.getSize()); // // System.out.println(bt.getParent(leaf1).getData()); } }
现在我们来前序遍历二叉树的同事,再颠倒左右孩子。在前序遍历的方法里做一些修改。
//前序遍历并颠倒左右子树 public void preOrderAndTransform(TreeNode node) { if (node != null) { // System.out.println(node.getData()); // 先保存左孩子结点 TreeNode lNode = node.getLchild(); node.setLchild(node.getRchild()); node.setRchild(lNode); preOrderAndTransform(node.getLchild()); preOrderAndTransform(node.getRchild()); } }
测试程序:
public static void main(String[] args) { TreeNode leaf1 = new TreeNode("5", null, null); // 没有左右孩子节点 TreeNode leaf2 = new TreeNode("7", null, null); // 没有左右孩子节点 TreeNode leaf3 = new TreeNode("9", null, null); // 没有左右孩子节点 TreeNode leaf4 = new TreeNode("11", null, null); // 没有左右孩子节点 TreeNode n3 = new TreeNode("6", leaf1, leaf2); // 根节点左子树 TreeNode n4 = new TreeNode("10", leaf3, leaf4); // 根节点右子树 TreeNode root = new TreeNode("8", n3, n4); // 创建根节点 BinaryTree bt = new BinaryTree(root); System.out.println("=======先序遍历======"); bt.preOrder(bt.root); System.out.println("=======中序遍历======"); bt.inOrder(bt.root); System.out.println("========后续遍历======="); bt.postOrder(bt.root); System.out.println("======镜像====="); // 镜像颠倒 bt.preOrderAndTransform(bt.root); System.out.println("=======先序遍历======"); bt.preOrder(bt.root); System.out.println("=======中序遍历======"); bt.inOrder(bt.root); System.out.println("========后续遍历======="); bt.postOrder(bt.root); // System.out.println(bt.getHeight()); // System.out.println(bt.getSize()); // // System.out.println(bt.getParent(leaf1).getData()); }
=======先序遍历====== 8 6 5 7 10 9 11 =======中序遍历====== 5 6 7 8 9 10 11 ========后续遍历======= 5 7 6 9 11 10 8 颠倒后 : =======先序遍历====== 8 10 11 9 6 7 5 =======中序遍历====== 11 10 9 8 7 6 5 ========后续遍历======= 11 9 10 7 5 6 8
循环的话使用while。用游标指向下一个待转换的结点,直到结点的左右孩子都为空。否则颠倒2个字结点。