您的位置:首页 > 理论基础 > 数据结构算法

算法与数据结构面试题(18)-二叉树镜像

2014-12-30 15:37 429 查看

题目

输入一颗二元查找树,将该树转换为它的镜像,
即在转换后的二元查找树中,左子树的结点都大于右子树的结点。
用递归和循环两种方法完成树的镜像转换。




解题思路

递归遍历每个结点,然后转换左右结点。

代码

前人写的二叉树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个字结点。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐