转载请注明出处:http://www.cnblogs.com/wuzetiandaren/p/4260432.html
声明:现大部分文章为寻找问题时在网上相互转载,此博是为自己做个记录记录,方便自己也方便有类似问题的朋友,本文的思想也许有所借鉴,但源码均为本人实现,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明。谢谢。
题目:输入一颗二元查找树,将该树转换为它的镜像, 即在转换后的二元查找树中,左子树的结点都大于右子树的结点, 用递归和循环两种方法完成树的镜像转换。
题目分析:
注:二叉排序树的中序遍历结果是升序排序的,因此将该树转换为它的镜像之后,该树的中序遍历结果应是降序排序的。
一、递归实现:
这种方式相对比较好实现,传入树的根节点,当节点不为空时,交换根节点的左右孩子,再递归交换左右子树的左右孩子。
算法实现:
1 private void exchangeRecursive(Node root){ 2 if(root!=null){ 3 swap(root); //交换根节点的左右子树 4 exchangeRecursive(root.left); //递归交换左子树 5 exchangeRecursive(root.right); //递归交换右子树 6 } 7 }
二、循环方式实现:
这种方式相对比较麻烦,下面给出两种实现方式:
(一)、借助先序遍历交换(后序遍历与此类似),可以用一个LinkedList的数据结构模拟栈来完成此操作。传入树的根节点root。
1.如果root为空则结束交换,否则root 进栈。
2.当栈不为空时进行如下操作:
a.弹出栈顶节点,交换栈顶节点的左右孩子。
b.如果栈顶元素的右孩子不为空,右孩子节点进栈;如果栈顶元素的左孩子不为空,左孩子节点进栈。
算法实现:
1 //运用先序遍历循环将该树转换为它的镜像,用LinkedList模拟栈来实现 DLR 2 private void exchangeCirculatory(Node root){ 3 if(root==null){ 4 return; 5 } 6 LinkedList<Node> nodelist = new LinkedList<Node>(); 7 System.out.println(); 8 nodelist.add(root); //根节点进栈 9 while(nodelist.size()!=0){ 10 root = nodelist.removeLast(); //获得栈顶元素 11 swap(root); 12 if(root.right!=null){ //如果栈顶元素的右孩子不为空,右孩子节点进栈 13 nodelist.add(root.right); 14 } 15 if(root.left!=null){ //如果栈顶元素的左孩子不为空,左孩子节点进栈 16 nodelist.add(root.left); 17 } 18 } 19 }
(二)、借助层序遍历交换,可以用一个LinkedList的数据结构模拟队列来完成此操作。传入树的根节点root。
1.如果root为空则结束交换,否则root 入队。
2.当队列不为空时进行如下操作:
a.队首元素出队,交换队首元素节点的左右孩子。
b.如果队首元素的左孩子不为空,左孩子节点入队;如果队首元素的右孩子不为空,右孩子节点进栈。
算法实现:
1 //层序遍历循环将该树转换为它的镜像,使用LinkedList数据结构来模拟队列 2 private void levelOrder(Node root){ 3 if(root==null){ 4 System.out.println(" 二叉树为空!"); 5 return; 6 } 7 System.out.println(" 这是二叉排序树的层序遍历结果:"); 8 LinkedList<Node> queue = new LinkedList<Node>(); 9 queue.add(root); //根节点先入队 10 while(queue.size()!=0){ 11 Node node = queue.removeFirst(); //得到并删除队列的第一个节点 12 swap(node); 13 if(node.left!=null){ //该节点的左孩子入队 14 queue.add(node.left); 15 } 16 if(node.right!=null){ //该节点的右孩子入队 17 queue.add(node.right); 18 } 19 } 20 System.out.println(); 21 }
java实现的完整源码:
1 package com.interview; 2 3 import java.util.LinkedList; 4 5 import com.interview._16LeverOrder.Node; 6 7 /** 8 * 题目:输入一颗二元查找树,将该树转换为它的镜像, 9 * 即在转换后的二元查找树中,左子树的结点都大于右子树的结点。 10 * 用递归和循环两种方法完成树的镜像转换。 11 * @author wjh 12 * 13 */ 14 public class _15MirrorTree { 15 16 /** 17 * @param args 18 */ 19 public static void main(String[] args) { 20 _15MirrorTree builder= new _15MirrorTree(); 21 int[] a = {56,45,47,67,35,76,22,89,91,27,11,21,19,87}; 22 Node root = null; 23 root = builder.buildTree(root, a); //1)创建二叉排序树 24 System.out.println("这是原二叉树的中序遍历结果:"); 25 builder.inOrder(root); //2)打印交换之前的二叉排序树的中序遍历结果 26 27 builder.exchangeRecursive(root); //3)递归交换二叉排序树的左右子树 28 System.out.println(" 这是用递归将该树转换为它的镜像的中序遍历结果:"); 29 builder.inOrder(root); //4)打印递归交换之后的二叉排序树的中序遍历结果 30 31 builder.exchangeRecursive(root); //5)将树转换回原二叉排序树 32 builder.exchangeCirculatory(root);//6)循环交换二叉排序树的左右子树 33 System.out.println(" 这是借助先序遍历循环将该树转换为它的镜像的中序遍历结果:"); 34 builder.inOrder(root); //7)打印循环交换之后的二叉排序树的中序遍历结果 35 36 builder.exchangeRecursive(root); //8)将树转换回原二叉排序树 37 builder.levelOrder(root); //9)层序交换二叉排序树的左右子树 38 System.out.println(" 这是借助层序循环将该树转换为它的镜像的中序遍历结果:"); 39 builder.inOrder(root); //10)打印循环交换之后的二叉排序树的中序遍历结果 40 } 41 42 //运用递归将该树转换为它的镜像 43 private void exchangeRecursive(Node root){ 44 if(root!=null){ 45 swap(root); //交换根节点的左右子树 46 exchangeRecursive(root.left); //递归交换左子树 47 exchangeRecursive(root.right); //递归交换右子树 48 } 49 } 50 51 //运用先序遍历循环将该树转换为它的镜像,用LinkedList模拟栈来实现 DLR 52 private void exchangeCirculatory(Node root){ 53 if(root==null){ 54 return; 55 } 56 LinkedList<Node> nodelist = new LinkedList<Node>(); 57 System.out.println(); 58 nodelist.add(root); //根节点进栈 59 while(nodelist.size()!=0){ 60 root = nodelist.removeLast(); //获得栈顶元素 61 swap(root); 62 if(root.right!=null){ //如果栈顶元素的右孩子不为空,右孩子节点进栈 63 nodelist.add(root.right); 64 } 65 if(root.left!=null){ //如果栈顶元素的左孩子不为空,左孩子节点进栈 66 nodelist.add(root.left); 67 } 68 } 69 } 70 71 //层序遍历循环将该树转换为它的镜像,使用LinkedList数据结构来模拟队列 72 private void levelOrder(Node root){ 73 if(root==null){ 74 System.out.println(" 二叉树为空!"); 75 return; 76 } 77 LinkedList<Node> queue = new LinkedList<Node>(); 78 queue.add(root); //根节点先入队 79 while(queue.size()!=0){ 80 Node node = queue.removeFirst(); //得到并删除队列的第一个节点 81 swap(node); 82 if(node.left!=null){ //该节点的左孩子入队 83 queue.add(node.left); 84 } 85 if(node.right!=null){ //该节点的右孩子入队 86 queue.add(node.right); 87 } 88 } 89 System.out.println(); 90 } 91 92 //交换节点的左右子树 93 private void swap(Node root){ 94 Node temp = root.left; 95 root.left = root.right; 96 root.right = temp; 97 } 98 99 //二叉树的中序遍历 100 private void inOrder(Node root){ 101 if(root==null){ 102 return; 103 } 104 else{ 105 inOrder(root.left); 106 System.out.print(root.data+" "); 107 inOrder(root.right); 108 } 109 } 110 111 //建二叉排序树 112 private Node buildTree(Node root, int[] data) { 113 for (int i = 0; i < data.length; i++) { 114 root=insert(root, data[i]); 115 } 116 return root; 117 } 118 119 //一次插入节点 120 private Node insert(Node node, int data) { 121 if (node == null) { 122 node = new Node(data,null,null); 123 }else{ 124 if(data <= node.data) { 125 node.left = insert(node.left, data); 126 } else { 127 node.right = insert(node.right, data); 128 } 129 } 130 return node; 131 } 132 133 //创建一个树节点类 134 class Node { 135 public int data; 136 public Node left; //指向左孩子的指针 137 public Node right; //指向右孩子的指针 138 public Node() { 139 super(); 140 } 141 public Node(int data, Node left, Node right) { 142 super(); 143 this.data = data; 144 this.left = left; 145 this.right = right; 146 } 147 } 148 149 }
运行结果:
这是原二叉树的中序遍历结果:
11 19 21 22 27 35 45 47 56 67 76 87 89 91
这是用递归将该树转换为它的镜像的中序遍历结果:
91 89 87 76 67 56 47 45 35 27 22 21 19 11
这是借助先序遍历循环将该树转换为它的镜像的中序遍历结果:
91 89 87 76 67 56 47 45 35 27 22 21 19 11
这是借助层序循环将该树转换为它的镜像的中序遍历结果:
91 89 87 76 67 56 47 45 35 27 22 21 19 11