zoukankan      html  css  js  c++  java
  • 1.把二元查找树转变成排序的双向链表

    转载请注明出处:http://www.cnblogs.com/wuzetiandaren/p/4256355.html 

    声明:现大部分文章为寻找问题时在网上相互转载,此博是为自己做个记录记录,方便自己也方便有类似问题的朋友,本文的思想也许有所借鉴,但源码均为本人实现,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明。谢谢。

    题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。

    题目分析:
      1.二叉树的节点有左右孩子指针,而双向链表的节点有前驱和后继指针。

      树节点的数据结构:

     1     //创建一个树节点类
     2     class Node {
     3         public int data;
     4         public Node left;  //指向左孩子的指针    
     5         public Node right;  //指向右孩子的指针    
     6         public Node() {
     7             super();
     8         }
     9         public Node(int data, Node left, Node right) {
    10             super();
    11             this.data = data;
    12             this.left = left;
    13             this.right = right;
    14         }
    15     }

      2.二叉排序树的中序遍历 结果刚好是升序的,改造时按照中序遍历的顺序重新改变节点的指针就行了,使其 左孩子指向前驱,右孩子指向后继。

    java实现源码:

      1 package com.interview;
      2 
      3 import java.util.LinkedList;
      4 
      5 /**
      6  * 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。
      7  *     要求不能创建任何新的结点,只调整指针的指向。
      8  * 分析:二叉树的节点有左右孩子指针,而双向链表有前驱和后继,二叉排序树的中序遍历
      9  * 是升序的结果,改造时按照中序遍历的顺序重新改变节点的指针就行了,使其
     10  * 左孩子指向前驱,有孩子指向后继
     11  * @author wjh
     12  *
     13  */
     14 public class _1TreeToDList {
     15 
     16     /**
     17      * @param args
     18      */
     19     public static void main(String[] args) {
     20         _1TreeToDList builder= new _1TreeToDList();
     21         int[] a = {56,45,47,67,35,76,22,89,91,27,11,21,19,87};
     22         Node tree = null;    
     23         LinkedList<Node> nodelist = new LinkedList<Node>();  //保存二叉树的中序遍历结果
     24         tree = builder.buildTree(tree, a);   //1)建二叉排序树    
     25         System.out.println("
    二叉排序树的中序遍历结果:");
     26         nodelist = builder.inOrder(tree,nodelist);//2)得到二叉树的中序遍历结果
     27         Node first = builder.translate(nodelist); //3)将二叉排序树转换成双链表
     28         builder.printList(first);    //4)打印双链表
     29     }
     30     
     31     //将二叉排序树改造为双向排序链表,左孩子指针指向前去,右孩子指针指向后继
     32     private Node translate(LinkedList<Node> nodelist){
     33         int size = nodelist.size();
     34         if(size==0){
     35             return null;
     36         }
     37         Node first = nodelist.get(0);  //链表的第一个节点,也是链表的入口
     38         if(size==1){         //只有一个节点的双链表
     39             first.left = null;   //因为是双链表而非双循环链表,不能first.left=first;
     40             first.right = null;
     41         }
     42         else if(size>1){     //有两个及以上节点的双链表
     43             first.left = null;
     44             first.right = nodelist.get(1);
     45             for(int i=1;i<size-1;i++){
     46                 nodelist.get(i).left = nodelist.get(i-1);
     47                 nodelist.get(i).right = nodelist.get(i+1);
     48             }
     49             nodelist.get(size-1).left = nodelist.get(size-2);
     50             nodelist.get(size-1).right = null;
     51         }
     52         return first;
     53     }
     54     
     55     //打印双链表
     56     private void printList(Node first){
     57         Node temp = first;   //temp 保存最后一个节点,以方便逆序打印
     58         System.out.println("
    
    这是正向打印双链表:");
     59         while(first!=null){
     60             if(first.right!=null){
     61                 System.out.print(first.data+"<->");
     62             }
     63             else{
     64                 System.out.print(first.data);
     65                 temp = first;   //最后一个节点
     66             }
     67             first = first.right;
     68         }
     69         first = temp;
     70         System.out.println("
    
    这是逆向打印双链表:");
     71         while(first!=null){
     72             if(first.left!=null){
     73                 System.out.print(first.data+"<->");
     74             }
     75             else
     76                 System.out.print(first.data);
     77             first = first.left;
     78         }
     79     }
     80     
     81     //二叉树的中序遍历
     82     private LinkedList<Node> inOrder(Node root,LinkedList<Node> nodelist){
     83         Node temp = root;
     84         if(root==null){
     85             return null;            
     86         }
     87         else{
     88             inOrder(root.left,nodelist);
     89             System.out.print(root.data+" ");
     90             nodelist.add(root);
     91             inOrder(root.right,nodelist);
     92         }
     93         return nodelist;
     94     }
     95     
     96     //建树
     97     private Node buildTree(Node root, int[] data) {
     98         System.out.println("建树过程(a<--b表示想a的左边插入b;a-->b表示想a的右边插入b):");
     99         for (int i = 0; i < data.length; i++) {
    100         root=insert(root, data[i]);
    101         }
    102         return root;
    103      }
    104                 
    105     //一次插入节点
    106     private Node insert(Node node, int data) {
    107         if (node == null) {
    108             node = new Node(data,null,null);
    109             System.out.println(node.data);
    110          }else{ 
    111             if(data <= node.data) {
    112                 System.out.print(node.data+"<--");
    113                 node.left = insert(node.left, data);
    114              } else {
    115                 System.out.print(node.data+"-->");
    116                 node.right = insert(node.right, data);
    117              }
    118          }
    119          return node;
    120     }
    121     
    122     //创建一个树节点类
    123     class Node<E> {
    124         public int data;
    125         public Node left;  //指向左孩子的指针    
    126         public Node right;  //指向右孩子的指针    
    127         public Node() {
    128             super();
    129         }
    130         public Node(int data, Node left, Node right) {
    131             super();
    132             this.data = data;
    133             this.left = left;
    134             this.right = right;
    135         }
    136     }
    137 }
    完整源码

    运行结果:

    建树过程(a<--b表示想a的左边插入b;a-->b表示想a的右边插入b):
    56
    56<--45
    56<--45-->47
    56-->67
    56<--45<--35
    56-->67-->76
    56<--45<--35<--22
    56-->67-->76-->89
    56-->67-->76-->89-->91
    56<--45<--35<--22-->27
    56<--45<--35<--22<--11
    56<--45<--35<--22<--11-->21
    56<--45<--35<--22<--11-->21<--19
    56-->67-->76-->89<--87

    二叉排序树的中序遍历结果:
    11 19 21 22 27 35 45 47 56 67 76 87 89 91

    这是正向打印双链表:
    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

  • 相关阅读:
    bzoj4044/luoguP4762 [Cerc2014]Virus synthesis(回文自动机+dp)
    bzoj4032/luoguP4112 [HEOI2015]最短不公共子串(后缀自动机+序列自动机上dp)
    bzoj3926/luoguP3346 [Zjoi2015]诸神眷顾的幻想乡(trie上构建广义后缀自动机)
    bzoj3144 [HNOI2013]切糕(最小割)
    知识点简单总结——原根和指标
    uoj86 mx的组合数 (lucas定理+数位dp+原根与指标+NTT)
    rest_framework 学习笔记(一)
    Django 数据库操作
    02-Kubenetes资源
    10-Helm
  • 原文地址:https://www.cnblogs.com/wuzetiandaren/p/4256355.html
Copyright © 2011-2022 走看看