1. 程式人生 > >中序線索二叉樹Java實現

中序線索二叉樹Java實現

/**
 * 線索樹結點類
 * @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);
	}
}

測試結果: