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(); } }