1. 程式人生 > >Java 通過先序中序序列生成二叉樹

Java 通過先序中序序列生成二叉樹

題目

  二叉樹的前序以及後續序列,以空格間隔每個元素,重構二叉樹,最後輸出二叉樹的三種遍歷方式的序列以驗證。

  輸入:

  1 2 3 4 5 6 7 8 9 10

  3 2 5 4 1 7 8 6 10 9

  輸出:

  1,2,3,4,5,6,7,8,9,10
  3,2,5,4,1,7,8,6,10,9
  3,5,4,2,8,7,10,9,6,1

分析

  以上述輸入為例,該樹的結構為:

    

  在解決這方面問題時,需要把控這幾個因素:
  (1)前序的第一個元素必為根節點;

  (2)中序中在根節點左邊的為左子樹,在根節點右邊的為右子樹。

  抓住上面兩點,就可以無限遞迴,從而產生一個完整的二叉樹。

演算法演算

   前序:1 2 3 4 5 6 7 8 9 10

   中序:3 2 5 4 1 7 8 6 10 9

    <預設優先處理左子樹>

   (1)第一次:

      產生節點 1。

      生成左子樹

          先序:2 3 4 5

          中序:3 2 5 4

      生成右子樹

          前序:6 7 8 9 10

          中序:7 8 6 10 9

    (2)第二次 

       產生節點 2(由左子樹得來,故為第一次結點的左子樹)。

       生成左子樹

          前序:3

          中序:3

       生成右子樹

          先序:4 5

          中序:5 4

    (3)第三次

        產生節點 3(同上,產生左子樹)

        <此處限定:當先序長度小於等於1時,直接Return>

    (4)第四次(因為Return,所以處理第二次產生的右子樹)

       產生結點 4

       生成左子樹

             先序:null

           中序:null

       生成右子樹

          先序:5

          後續:5

         <此處限定:當新生成的左(右)序列為空時,則只進行右(左)序列的處理,並將為空的節點初始化為null>

    ……

    以此類推,即可輕鬆生成一棵二叉樹。

實現程式碼

package DataStructe;

import java.util.ArrayList;
import java.util.Scanner;

public class TreeReBuild {
    /*先序(DLR)、中序(LDR)遍歷對應的三個陣列*/
    static ArrayList<Integer> DLR=new ArrayList<Integer>();
    static ArrayList<Integer> LDR=new ArrayList<Integer>();
    static node root=new node();
    
    
    /*二叉樹的結點結構*/
    static class node{
        node rchild;
        node lchild;
        int data;
        node(int ndata)
        {
            data=ndata;
            rchild=null;
            lchild=null;
        }
        public node() {
            rchild=null;
            lchild=null;
        }
    }
    

    /*核心演算法*/
    static void reBuildTreeprocess(node x,ArrayList<Integer> qx,ArrayList<Integer> zx)
    {
        x.data=qx.get(0);//前序第一個元素必為根節點
        if(qx.size()<=1)
        {
            return;
        }
        x.lchild=new node();
        x.rchild=new node();
        //兩個序列的拆分索引
        int rootindex = 0;
        int qxindex=0;
        /*拆分序列*/
        ArrayList<Integer>newqxleft    = new ArrayList<Integer>();
        ArrayList<Integer>newqxright= new ArrayList<Integer>();
        ArrayList<Integer>newzxleft = new ArrayList<Integer>();
        ArrayList<Integer>newzxright = new ArrayList<Integer>();
        //拆分中序
        for(int j=0;j<zx.size();j++)
        {
            if(zx.get(j)==x.data)
            {
                zx.remove(j);
                j--;
                rootindex=j;
                break;
            }
        }
        
        //生成新的中序(左)
        for(int j=0;j<=rootindex;j++){
            
            newzxleft.add(zx.get(j));
        }
        //生成新的中序(右)
        for(int j=rootindex+1;j<zx.size();j++)
        {
            newzxright.add(zx.get(j));
        }
        
        
        
        //拆分前序,確定分離的元素索引
        if(newzxright.isEmpty())
        {
            //中序右為空,前序全為左子樹
            for(int i=1;i<qx.size();i++)    
            {
                newqxleft.add(qx.get(i));
            }
            x.rchild=null;
            reBuildTreeprocess(x.lchild, newqxleft, newzxleft);
        }
        else{
            if(newzxleft.isEmpty())
            {
                //中序左為空,前序全為右子樹
                for(int i=1;i<qx.size();i++)    
                {
                    newqxright.add(qx.get(i));
                }
                x.lchild=null;
                reBuildTreeprocess(x.rchild, newqxright, newzxright);
            }
            else {
                //均不為空,分別生成
                outer:        for(int r=0;r<qx.size();r++)
                {
                    
                    for(int i=0;i<newzxright.size();i++)
                    {
                        
                        if(qx.get(r)==newzxright.get(i))
                        {
                            
                            qxindex=r;
                            break outer;
                        }
                    }
                }
            
            
            for(int t=1;t<qxindex;t++)
            {
                newqxleft.add(qx.get(t));
            }
            for(int y=qxindex;y<qx.size();y++)
            {
                newqxright.add(qx.get(y));
            }
            reBuildTreeprocess(x.lchild, newqxleft, newzxleft);
            reBuildTreeprocess(x.rchild, newqxright, newzxright);
            }
        }
    }
    /*先序遍歷,用於測試結果*/
    static void XSearch(node x)
    {
        if (x==null) {
            return;
        }
        System.out.print(x.data+",");
      if (x.lchild!=null) {
          XSearch(x.lchild);
        }
      
      if(x.rchild!=null){
          XSearch(x.rchild);
          }
    }
    
    
    
    /*中續遍歷,用於測試結果*/
    static void ZSearch(node x)
    {
        if (x==null) {
            return;
        }
      if (x.lchild!=null) {
          ZSearch(x.lchild);
        }
      System.out.print(x.data+",");
      if(x.rchild!=null){
          ZSearch(x.rchild);
          }
      
    }
    
    
    /*後續遍歷,用於測試結果*/
    static void HSearch(node x)
    {
        if (x==null) {
            return;
        }
      if (x.lchild!=null) {
          HSearch(x.lchild);
        }
      if(x.rchild!=null){
          HSearch(x.rchild);
          }
      System.out.print(x.data+",");
    }
    
    
    
    
    
    public static void main(String[] args) {
        Scanner getin=new Scanner(System.in);
        
        /*讀入先序序列*/
        String readydata=getin.nextLine();
        String []DLRdata=readydata.split(" ");
        for(int i=0;i<DLRdata.length;i++)
        {
            int qxdata=Integer.parseInt(DLRdata[i]);
            DLR.add(qxdata);
        }
        
        
        /*讀入中序序列*/
        readydata=getin.nextLine();
        String[]LDRdata=readydata.split(" ");
        for(int i=0;i<LDRdata.length;i++)
        {
            int zxdata=Integer.parseInt(LDRdata[i]);
            LDR.add(zxdata);
        }
        reBuildTreeprocess(root, DLR, LDR);
        
        XSearch(root);
        System.out.println();
        ZSearch(root);
        System.out.println();
        HSearch(root);
        System.out.println();
        
        
    }

}