线索二叉树模型的建立与遍历

线索二叉树是在普通二叉树模型上建立线索后的树模型,再建立了线索后我们可以在O(n)的时间内遍历该树,并且很方便的找出某个节点的前驱节点和后继节点,我们的代码首先建立一棵普通的二叉树,然后利用递归的方式建立线索,并且提供一个遍历算法,其中有一些细节是需要我们多加注意的。不多说了,上代码

/**
 * @author pc
 * 线索二叉树模型
 */
public class ThreadTree {
	
	private Node root;
	private Node pre;
	
	 private class Node{  
	        private Node left;  
	        private Node right;  
	        private int  data;
	        private int  ltag;   //ltag=0表示指向左孩子节点,ltag=1表示指向线索即前驱节点
	        private int  rtag;   //rtag=0表示指向右孩子节点,rtag=1表示指向线索即后继节点
	        public Node(int data){  
	            this.left = null;  
	            this.right = null;  
	            this.data = data;
	            this.ltag =0;        
	            this.rtag =0;
	        }
			public Node getLeft() {
				return left;
			}
			public void setLeft(Node left) {
				this.left = left;
			}
			public Node getRight() {
				return right;
			}
			public void setRight(Node right) {
				this.right = right;
			}
			public int getData() {
				return data;
			}
			public void setData(int data) {
				this.data = data;
			}
			public int getLtag() {
				return ltag;
			}
			public void setLtag(int ltag) {
				this.ltag = ltag;
			}
			public int getRtag() {
				return rtag;
			}
			public void setRtag(int rtag) {
				this.rtag = rtag;
			} 
	    }
	 
	 public ThreadTree(){
		 root=null;
		 pre=null;
	 }
	 
	/**
	 * 首先根据一个数组来创建普通二叉树
	 * 
	 * @param a
	 * n+1个数据组成的数组,其中a[0]=-1不参与树的创建,a[1]~a[n]代表数的节点,a[2*i]是a[i]的左子结点,
	 * a[2*i+1]是右子节点
	 */
	private Node buildTreeByArray(int[] a, int n) {
		Node[] p = new Node[n + 1];
		p[0] = null;
		for (int i = 1; i <= n; i++) {
			if (a[i] == -1) {
				p[i] = null;
			} else {
				p[i] = new Node(a[i]);
			}
		}
		for (int i = 1; i <= n / 2; i++) {
			if (a[i] != -1) {
				if ((2 * i <= n) && a[2 * i] != -1) {
					p[i].setLeft(p[2 * i]);
				}
				if ((2 * i + 1 <= n) && (a[2 * i + 1] != -1)) {
					p[i].setRight(p[2 * i + 1]);
				}
			}
		}
		return p[1];
	}
	
	/**
	 * 递归的线索化过程
	 * pre指向前驱节点,p指向当前节点
	 */
	private void Thread(Node p){
		if(p!=null){
			Thread(p.left);
			if(p.left==null){
				p.ltag=1;
				p.left=pre;
			}
			else{
				p.ltag=0;
			}
			if(pre.right==null){
				pre.rtag=1;
				pre.right=p;
			}
			else{
				pre.rtag=0;
			}
			pre=p;
			Thread(p.right);
		}
	}
	
	/**
	 * 真正建立二叉线索树的函数
	 * 其中首先建立一棵普通二叉树,然后再对其进行线索化
	 * 最后返回一个root节点,left指向二叉树的根节点,right指向遍历时的最后一个节点
	 * @param a
	 * @param n
	 */
	public Node createThreadTree(int[] a, int n){
		Node bt=buildTreeByArray(a, n);
		root=new Node(0);
		root.ltag=0;
		root.rtag=1;
		root.right=bt;       //这一步不能少,否则线索化时会把root节点的右指针指向遍历时的第一个节点
		if(bt==null){
			root.left=root;
		}
		else{
			root.left=bt;
			pre=root;
			Thread(bt);
			pre.right=root;
			pre.rtag=1;
			root.right=pre;
		}
		return root;
	}
	
	/**
	 * 对中序线索二叉树进行遍历
	 * @param root
	 */
	public void ThInOrder(Node root){
		Node p=root.left;
		while(p!=root){             //注意现在空树的条件是p==root即root.left=root
			while(p.ltag==0)        //找出最左下方节点
				p=p.left;
			System.out.print(p.data+" ");
			while(p.rtag==1&&p.right!=root){   //当访问完最左下节点后顺着右线索访问即可
				p=p.right;
				System.out.print(p.data+" ");
			}
			p=p.right;
		}
	}
	
	public static void main(String args[]){
		 int[] a={-1,2,4,6,7,8,9,-1,12,13};
		 ThreadTree thread=new ThreadTree();
		 Node node=thread.createThreadTree(a, 9);
		 thread.ThInOrder(node);
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值