线索二叉树

/*====知识总结=*/

//1线索二叉树就是比一般的二叉树多了个线索,即指向结点前驱和后继的指针

//2线索二叉树基本结构分为LTag,lchild,data,RTag,rchild.即左标志,左指针,结点数据,右指针,右标志。

//3标志位的取值决定指针的指向(为线索,指向结点前驱或后继;或位正常指针,指向左右孩子结点),这个程 序的设定就是LTag1,指向左子树(右同)。LTag0,指向结点的前驱或后继。

package 线索二叉树;

//线索二叉树的声明。
class ThreadNode{
	
	int value;                       //结点都值。
	int left_Thread;                 //结点的左标志。
	int right_Thread;                //右标志
	ThreadNode left_Node;            //左结点
	ThreadNode right_Node;           //右结点
	//树结点的构造方法。
	public ThreadNode(int value){
		this.value=value;
		this.left_Thread = 0;
		this.right_Thread = 0;
		this.left_Node = null;
		this.right_Node = null;
	}
}

//线索二叉树的类声明。

class Threaded_Binary_Tree{
	public ThreadNode rootNode;    //线索二叉树的根节点;
	
	//无传入参数的构造函数。
	
	public Threaded_Binary_Tree(){
		rootNode = null;
	}
	
	//构造函数,用来建立线索二叉树,传入参数为一个数组。
	
	public Threaded_Binary_Tree(int data[]){
		for(int i = 0;i<data.length;i++){
			Add_Node_To_Tree(data[i]);
		}
	}
	
	//将指定的值加入线索二叉树适当的结点。
	
	void Add_Node_To_Tree(int value){
		ThreadNode newnode = new ThreadNode(value);     //创建一个新结点,用于添加到二叉树。
		ThreadNode  current;                            //声明当前结点。
		ThreadNode parent;                              //声明一个父亲结点。
		ThreadNode previous = new ThreadNode(value);    //创建一个结点,用来指示上个结点。
		
		int pos;       
		
		//设定线索二叉树的开头结点。
		
		if(rootNode==null){
			rootNode = newnode;                       //将newnode的引用赋给rootNode;
			//rootNode.left_Node = rootNode;            
			//rootNode.right_Node = null;
			//rootNode.left_Thread = 0;
			rootNode.right_Thread = 1;
			//rootNode = new ThreadNode(value);
			return;                                  //结束该方法,不执行这条语句后面的语句。。
		}
		
		//设定开头结点所指的结点。
		
		current = rootNode.right_Node;              //将根结点的左子结点的引用赋给current
		
		if(current==null){
			
			rootNode.right_Node = newnode;
			//newnode.left_Node = rootNode;
			//newnode.right_Node = rootNode;
			return;
			
		}
		
		//依照一下规则,建立线索二叉树。
		
		parent = rootNode;  //父结点指向根结点。即每次从根结点开始建立线索二叉树。
		  pos = 0;
		
		while(current!=null){     //current不是空值开始循环。
			
			if(current.value>value){     //current结点的值大于当前的值,建立左子树。执行大括号里面的语句。
				
				if(pos!=-1){
					pos=-1;
					previous = parent;   //令previous指向parent
				}
				
				parent=current;        //令parent指向current
				
				if(current.left_Thread==1)   //current的左标志为1;即left_Node为正常指针,即current结点有左子结点。
					current = current.left_Node; //将current。left_Node的引用赋给current,即将current的左子结点设置为当前结点。
				
					else                   //当前结点没有左子结点,即当前结点为叶子结点。
						current = null;     //令current为0;结束本次循环,执行循环体下面的语句。
			}
			
			else{                      //current结点的值小于当前的值,右左子树。执行大括号里面的语句。
				
				if(pos!=1){
					pos=1;
					previous = parent;  //令previous指向parent
				}
				
				parent = current;        //令parent指向current
				
				if(current.right_Thread==1)  //current的左标志为1;即left_Node为正常指针,即current结点有左子结点。
					current = current.right_Node;   //将current。left_Node的引用赋给current,即将current的左子结点设置为当前结点。
				
				else
					current = null;       //令current为0;结束本次循环。
			} 
			
		}
		
		//将结点加入二叉树。
		
		if(parent.value>value){     //实际上是current结点,两个是结点是一致的。parent=current;
			                        //parent结点的值大于当前的值,建立左子树。
			parent.left_Thread=1;    //令left_Thread为1,即其存在左子结点
			parent.left_Node=newnode;  //将新结点加入二叉树中。
			newnode.left_Node=previous; //左指针指向指向前驱结点。
			newnode.right_Node=parent;  //指向后继结点。
			
		}
		
		else{                      //parent结点的值大于当前的值,建立右子树
			
			parent.right_Thread=1;
			parent.right_Node = newnode;
			newnode.left_Node = parent;
			newnode.right_Node = previous;
			
		}
		
		return;	                //结束该方法,执行其他语句。
		
	}
	
	//线索二叉树中序遍历。
	
	void print(){
		
		ThreadNode tempNode;   //声明一个临时结点tempNode;
		tempNode = rootNode;   //将rootNode的引用赋给tempNode
		
		//循环判断,中序遍历。
		
		
		do{
			
			if(tempNode.right_Thread==0){           //没有右子结点。即当前结点为叶子结点,
				
				tempNode=tempNode.right_Node;       //指向后继结点。
			}
			
			else{                                   //有右子结点。
				
				tempNode = tempNode.right_Node;     //将tempNode。right_Node的引用赋给tempNode,即将tempNode的右子结点设置为当前结点,即线索树真正的结点。
				
				while(tempNode.left_Thread!=0){     //有左子结点。
					
					tempNode = tempNode.left_Node;  //将tempNode。right_Node的引用赋给tempNode,即将tempNode的左子结点设置为当前结点。
				}
			}
			
			
			if(tempNode!=rootNode)                  //如果临时结点不等于开头节点。输出临时结点的值
				
				System.out.println("["+tempNode.value+"]");
			
		}while(tempNode!=rootNode);               //条件成立循环,(最后一个结点的后继会指向rootNode结点。)
	}
}

public class demoThreadTree {

	public static void main(String[] args) {
		
		System.out.println("线索二叉树经建立后,以中序追踪能有排序的效果");
		
        System.out.println("除了第一个数字作为线索二叉树的开头节点外");
        
        int [] data1 = {0,10,20,30,100,399,453,43,237,373,655};
        
        Threaded_Binary_Tree tree1 = new Threaded_Binary_Tree(data1);
        
        System.out.println("=====================================");
        
        System.out.println("范例1");
        
        System.out.println("数字由小到大的排列顺序结果为: ");
        
        tree1.print();
        
        
        int[]data2 = {0,101,118,87,12,765,65};
        
        Threaded_Binary_Tree tree2 = new Threaded_Binary_Tree(data2);
        
        System.out.println("=====================================");
        
        System.out.println("范例2");
        
        System.out.println("数字由小到大的排列顺序结果为: ");
        
        tree2.print();
        
        }
	}

/程序总结=/

1.这个程序比较复杂,废了很大的功夫,才读懂整个程序,有很多地方设置的比较复杂,很冗余,完全可以删除一些语句,简化程序。

2.例如那个建立线索二叉树,用了一个循环既然只是为了遍历叶子结点,后面还用了一个循环来添加新结点,这个完全可以合并的。自己能力有限只能看看了。

3.自己通过这个程序,学会了如何debug。下次遇到复杂的程序,自己先仔细读懂,慢一点没关系不着急,如果读不懂,不知道程序如何运行的,就运用debug。

4.这个程序超出自己的知识高度,理解思想和读懂程序就好。

5.eclipse debug视频连接: https://www.bilibili.com/video/av31632777?from=search&seid=2095717832218173241

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值