zoukankan      html  css  js  c++  java
  • 15.输入一颗二元查找树,将该树转换为它的镜像, 即在转换后的二元查找树中,左子树的结点都大于右子树的结点, 用递归和循环两种方法完成树的镜像转换

    转载请注明出处: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

  • 相关阅读:
    《TCP/IP详解》读书笔记
    更改vsts源代码绑定服务器地址方法
    t-sql或mssql怎么用命令行导入数据脚本
    t-sql中字符串前加N代表什么意思
    C#连接mariadb代码及方式
    sp_executesql动态执行sql语句并将结果赋值给一变量
    mariadb配置允许远程访问方式
    将DataTable转换为List,将List转换为DataTable的实现类
    SQL update select语句
    怎么区分MSSQL中nvarchar和varchar的区别?
  • 原文地址:https://www.cnblogs.com/wuzetiandaren/p/4260432.html
Copyright © 2011-2022 走看看