中序線索二叉樹Java實現
阿新 • • 發佈:2018-12-25
/** * 線索樹結點類 * @author liangxiamoyi * */ public class ThreadNode { /** * 1標識左節點為前驅結點,0標識左節點為左子節點 */ protected int lThread; /** * 1標識右節點為後繼結點,0標識右節點為右子節點 */ protected int rThread; /** * 左節點 */ protected ThreadNode left; /** * 右節點 */ protected ThreadNode right; /** * 資料 */ protected char data; /** * 建構函式 * @param item 資料值 */ public ThreadNode(char item){ this.data=item; this.lThread=this.rThread=0; this.left=this.right=null; } }
import java.util.Scanner; /** * 中序線索二叉樹 * @author liangxiamoyi * */ public class ThreadInTree { /** * 根節點 */ private ThreadNode root; /** * 終止字元 */ private char stop; /** * 中序二叉樹的線索化,指向上次遍歷的結點 */ private ThreadNode pre; /** * 構造方法 * @param t 根節點 */ public ThreadInTree(ThreadNode t){ this.root=t; this.pre=null; } /** * 返回以結點t為根節點的中序線索二叉樹的中根序列的第一個結點 * @param t 根節點 * @return 結點 */ public ThreadNode firstInOrder(ThreadNode t){ if(t==null){ return null; } ThreadNode q=t; while(q.lThread==0){ q=q.left; } return q; } /** * 返回以結點t為根節點的中序線索二叉樹的中根序列的最後一個結點 * @param t 根節點 * @return 結點 */ public ThreadNode lastInOrder(ThreadNode t){ if(t==null){ return null; } ThreadNode q=t; while(q.rThread==0){ q=q.right; } return q; } /** * 搜尋在以t為根的中序線索二叉樹中p的中根前驅結點 * @param t 根結點 * @param p 結點 * @return 前驅結點 */ public ThreadNode preInOrder(ThreadNode t,ThreadNode p){ if(t==null||p==null){ return null; } ThreadNode q; if(p==firstInOrder(t))return null; if(p.lThread==1)return p.left; return lastInOrder(p.left); } /** * 搜尋在以t為根的中序線索二叉樹中p的中根後繼結點 * @param t 根結點 * @param p 結點 * @return 後繼結點 */ public ThreadNode postInOrder(ThreadNode t,ThreadNode p){ if(t==null||p==null)return null; ThreadNode q; if(p==lastInOrder(t))return null; if(p.rThread==1)return p.right; return firstInOrder(p.right); } /** * 中根遍歷以t為根的中序線索二叉樹 * @param t 根結點 */ public void inOrder(ThreadNode t){ if(t==null)return; ThreadNode q; for(q=firstInOrder(t);q!=null;q=postInOrder(t, q)) System.out.print(q.data+" "); } /** * 插入結點p作為結點s的右子節點 * @param p 插入的結點 * @param s */ public void insertRight(ThreadNode p,ThreadNode s){ if(s==null||p==null)return; p.right=s.right; p.rThread=s.rThread; p.left=s; p.lThread=1; if(s.rThread==0){ ThreadNode q=s.right; q=firstInOrder(q);//令q為s的右子樹的最左結點 q.left=p;//令q的前驅指標指向p } s.right=p; s.rThread=0; } /** * 插入結點p作為結點s的左子節點 * @param p 插入的結點 * @param s */ public void insertLeft(ThreadNode p,ThreadNode s){ if(s==null||p==null)return; p.left=s.left; p.lThread=s.lThread; p.right=s; p.rThread=1; if(s.lThread==1&&s.left!=null){ s.left.right=p; } if(s.lThread==0){ lastInOrder(s.left).right=p;//令p的左子樹的最右結點的後繼指標指向p } s.left=p; s.lThread=0; } /** * 刪除結點s的右子節點p * @param p * @param s */ public void deleteRight(ThreadNode p,ThreadNode s){ if(s==null||p==null)return; if(p.lThread==1&&p.rThread==1){ s.right=p.right; s.rThread=1; } if(p.lThread==1&&p.rThread==0){ ThreadNode temp=firstInOrder(p.right); s.right=p.right; temp.left=s; } if(p.lThread==0&&p.rThread==1){ ThreadNode temp=lastInOrder(p.left); s.right=p.left; temp.right=p.right; } if(p.lThread==0&&p.rThread==0){ ThreadNode temp1=firstInOrder(p.right); ThreadNode temp=lastInOrder(p.left); temp.right=p.right; temp.rThread=0; s.right=p.left; temp1.left=temp; } } /** * 刪除結點s的左子節點p * @param p * @param s */ public void deleteLeft(ThreadNode p,ThreadNode s){ if(s==null||p==null)return; if(p.lThread==1&&p.rThread==1){ s.left=p.left; s.lThread=1; } if(p.lThread==0&&p.rThread==1){ ThreadNode temp=lastInOrder(p.left); s.left=p.left; temp.right=s; } if(p.lThread==1&&p.rThread==0){ ThreadNode temp=firstInOrder(p.right); s.left=p.right; temp.left=p.left; } if(p.lThread==0&&p.rThread==0){ ThreadNode temp1=lastInOrder(p.left); ThreadNode temp=firstInOrder(p.right); temp1.right=p.right; temp1.rThread=0; s.left=p.left; temp.left=temp1; } } /** * 建立以root為根節點的中序線索二叉樹 * @param stop 輸入終止符 */ public void createThreadInTree(char stop){ this.stop=stop; this.root=create(); ThreadInTree(this.root); } /** * 建立以root為根結點的尚未線索化的二叉樹 * @return 根節點 */ public ThreadNode create(){ ThreadNode t,l,r; char item; Scanner sc=new Scanner(System.in); item=sc.next().charAt(0); if(item==stop){ t=null; return t; } else{ t=new ThreadNode(item); l=create(); t.left=l; r=create(); t.right=r; return t; } } /** * 將以root為根節點的二叉樹化為中序線索二叉樹 */ public void ThreadInTree(ThreadNode t){ if(t==null)return; ThreadInTree(t.left); if(t.left==null){//左子樹為空,設定前驅結點 t.lThread=1; if(pre!=null){ t.left=pre; } } if(t.right==null){//先標記,在下一次遍歷設定後繼結點 t.rThread=1; } if(pre!=null&&pre.rThread==1){//為上次被標記的結點設定後繼結點 pre.right=t; } pre=t;//記錄當前結點 ThreadInTree(t.right);//右子樹 } /** * 獲得中序遍歷的第一個結點 * @return */ public ThreadNode getFirst(){ return firstInOrder(root); } /** * 獲得中序遍歷的最後一個結點 * @return */ public ThreadNode getLast(){ return lastInOrder(root); } /** * 搜尋在以root為根的樹中資料為item的結點 * @param root * @param item * @return */ public ThreadNode find(ThreadNode root,char item){ if(root==null)return null; ThreadNode q; for(q=firstInOrder(root);q!=null;q=postInOrder(root, q)){ if(q.data==item){ return q; } } return null; } public static void main(String[] args){ ThreadInTree tit=new ThreadInTree(null); tit.createThreadInTree('z'); System.out.println("中序遍歷的第一個節點為:"); System.out.println(tit.getFirst().data); System.out.println("中序遍歷的最後一個結點:"); System.out.println(tit.getLast().data); System.out.println("中序遍歷為:"); tit.inOrder(tit.root); System.out.println(""); ThreadNode a=new ThreadNode('g'); ThreadNode c=new ThreadNode('h'); ThreadNode b=tit.find(tit.root, 'c'); System.out.println("在c插入左子節點g後中序遍歷:"); tit.insertLeft(a,b); tit.inOrder(tit.root); System.out.println(""); System.out.println("在c插入右子節點h後中序遍歷:"); tit.insertRight(c,b); tit.inOrder(tit.root); System.out.println(""); tit.deleteLeft(tit.find(tit.root, 'e'), tit.find(tit.root, 'd')); System.out.println("d刪除左子節點e後中序遍歷:"); tit.inOrder(tit.root); System.out.println(""); tit.deleteRight(tit.find(tit.root, 'h'), tit.find(tit.root, 'c')); System.out.println("c刪除右子節點h後中序遍歷:"); tit.inOrder(tit.root); } }
測試結果: