java implementation-data structure of the binary tree (three): clue binary tree

Data structure of binary tree (3): clue binary tree

Basic introduction:
Threaded BinaryTree:
A binary linked list with n nodes contains n+1 [formula 2n-(n-1)=n+1] null pointer fields. Use the null pointer and in the binary linked list to store pointers to the predecessor and successor nodes of the node in a certain traversal order (this additional pointer becomes a "clue").
This kind of binary linked list with clues is called a clue Linked list, the corresponding binary tree becomes the clue binary tree. According to the different nature of the clues, the clue binary tree can be divided into three types: the preorder clue binary tree, the middle order clue binary tree and the postorder clue binary tree.

The previous node of a node is called the predecessor node. The
next node of a node becomes the successor node. The
official explanation is too straightforward. Please see the figure below:
Insert picture description here
we can see from the figure above that this is a complete binary tree, but, For leaf nodes 8, 10, 14, and 6, their left and right nodes do not exist (6 has only the left node), that is to say, there are pointers on their nodes that have not been used.
The so-called clue binary tree is to use these unused pointers so that each node can point to its own front and rear nodes.
And why is it divided into a pre-order clue binary tree, a middle-order clue binary tree and a post-order clue binary tree What about the three situations? This is because when we are traversing the clueed binary tree, the clue pointers point to different points due to different traversal methods.

If you still don’t understand this, please see the following graphic explanation:

Binary tree before
Insert picture description here
clueing : its in-order traversal result is [8,3,10,1,14,6];
through the result of in-order traversal to de-cue the binary tree, the result is as follows:
Insert picture description here
As can be seen from the above figure,
8-node in-order traversal Time is in the first place, so its predecessor node does not exist, and its successor node is 3. So its free pointer is used to make its successor node point to 3.
The 10-node in-order traversal is ranked third, and its left and right node pointers are idle, so we can point its left node to its predecessor node 3, and the right node to its successor node 1.
Similarly, the 14-node The left and right pointers are the same as above.

Problem analysis:
from the above pictures and texts, everyone must have a clear understanding of the clue binary tree.
However, there are bound to be some difficulties when the code is implemented in this way to build a threaded binary tree. ·
When the binary tree is threaded, the left and right of the Node node will have the following situations:
left points to the left subtree, or it may point to the predecessor node. For example, the left subtree of node 1 in the figure points to its left subtree, while node 10 points to its predecessor node.
Right is the same.
Therefore, this provides a certain degree of difficulty for our code implementation.

The reference code is as follows:


public class ThreadedBinaryTreeDemo {
    
    
	public static void main(String[] args) {
    
    
		BinaryTree threadBinaryTree=new BinaryTree();
		HeroNode root=new HeroNode("孙悟空");
		HeroNode node1=new HeroNode("猪八戒");
		HeroNode node2=new HeroNode("唐三藏");
		HeroNode node3=new HeroNode("沙和尚");
		HeroNode node4=new HeroNode("牛魔王");
		HeroNode node5=new HeroNode("红孩儿");
		HeroNode node6=new HeroNode("白骨精");
		threadBinaryTree.setRoot(root);
		root.setLeftNode(node1);
		root.setRightNode(node2);
		node1.setLeftNode(node3);
		node1.setRightNode(node4);
		node2.setLeftNode(node5);
		node2.setRightNode(node6);
		
		threadBinaryTree.threadNodes(); 
		threadBinaryTree.threadshow();
	}
}

class BinaryTree{
    
    
	HeroNode root;
	//指向前驱节点的指针
	//在递归进行线索化时,pre总是保留前一个节点
	HeroNode pre=null;
	public void setRoot(HeroNode root) {
    
    
		this.root=root;
	}
	//重载threadNodes方法,使node首先为root
	public void  threadNodes() {
    
    
		threadNodes(root);
	}
	//线索化二叉树的方法(中序遍历方式)
	public void threadNodes(HeroNode node) {
    
    
		//先判断node是否为空,为空则不再线索化
		if(node==null) {
    
    
			return;
		}
		//先线索化左子树
		threadNodes(node.getLeftNode());
		//线索化当前节点
		//先处理前驱节点
		if(node.leftNode==null) {
    
    
			//让当前节点额左指针指向前驱节点
			node.setLeftNode(pre);
			//设置当前节点的type为1
			node.setLeftType(1);
		}
		//再处理后继节点
		if(pre!=null&&pre.getRightNode()==null) {
    
    
			//让前驱节点的右指针指向当前节点
			pre.setRightNode(node);
			//修改前驱节点的type为1
			pre.setRightType(1);
		}
		//每处理一个节点后,让当前节点时下一个节点的前驱节点
		pre=node;
		
		
		//再线索化右子树
		threadNodes(node.getRightNode());
	}
	
	//循环遍历线索化二叉树(中序遍历顺序)
	public void threadshow() {
    
    
		//定义一个变量,存储当前遍历的节点,从root开始
		 HeroNode node=root;
		 while(node!=null) {
    
    
			 while(node.getLeftType()==0) {
    
    
				 node=node.getLeftNode();
			 }
			 
			 System.out.println(node.value);
			 
			 while(node.getRightType()==1) {
    
    
				 node=node.getRightNode();
				 System.out.println(node.value);
			 }
			 node=node.getRightNode();
		 }
	}
	
	
	public void frontShow() {
    
    
		if(this.root!=null) {
    
    
			this.root.frontShow();
		}else {
    
    
			System.out.println("二叉树为空,无法遍历");
		}
	}
	public void middleShow() {
    
    
		if(this.root!=null) {
    
    
			this.root.middleShow();
		}else {
    
    
			System.out.println("二叉树为空,无法遍历");
		}
	}
	public void endShow() {
    
    
		if(this.root!=null) {
    
    
			this.root.endShow();
		}else {
    
    
			System.out.println("二叉树为空,无法遍历");
		}
	}
	public void deleteNode(String value) {
    
    
		if(this.root!=null) {
    
    
			if(this.root.value.equals(value)) {
    
    
				this.root=null;
			}else {
    
    
				root.deleteNode(value);
			}
		}else {
    
     
			System.out.println("空树,无法删除");
		}
	}
}

class HeroNode{
    
    
	HeroNode leftNode;
	HeroNode rightNode;
	String value;
	
	//两个参数解决左右子树和前后节点的的混乱问题
	//如果leftType或rightType==0,表示指向的是左右子树,如果等于1,表示指向的是前后节点
	private int leftType;
	private int rightType;
	
	
	public HeroNode(String value) {
    
    
		this.value=value;
	}
	
	
	public int getLeftType() {
    
    
		return leftType;
	}


	public void setLeftType(int leftType) {
    
    
		this.leftType = leftType;
	}


	public int getRightType() {
    
    
		return rightType;
	}


	public void setRightType(int rightType) {
    
    
		this.rightType = rightType;
	}


	public HeroNode getLeftNode() {
    
    
		return leftNode;
	}
	public void setLeftNode(HeroNode leftNode) {
    
    
		this.leftNode=leftNode;
	}
	
	public HeroNode getRightNode() {
    
    
		return rightNode;
	}
	
	public void setRightNode(HeroNode rightNode) {
    
    
		this.rightNode=rightNode;
	}
	
	@Override
	public String toString() {
    
    
		return "HeroNode [leftNode=" + leftNode + ", rightNode=" + rightNode + ", value=" + value + "]";
	}
	
	/**
	 * 三种遍历方法
	 */
	//前序遍历:
	public void frontShow() {
    
    
			System.out.println(this.value);
		if(this.getLeftNode()!=null) {
    
    
			this.getLeftNode().frontShow();
		}
		if(this.getRightNode()!=null) {
    
    
			this.getRightNode().frontShow();
		}
	}
	//中序遍历
	public void middleShow() {
    
    
		if(this.getLeftNode()!=null) {
    
    
			this.getLeftNode().middleShow();
		}
		System.out.println(this.value);
		
		if(this.getRightNode()!=null) {
    
    
			this.getRightNode().middleShow();
		}
	}
	//后序遍历
	public void endShow() {
    
    
		if(this.getLeftNode()!=null) {
    
    
			this.getLeftNode().endShow();
		}
		if(this.getRightNode()!=null) {
    
    
			this.getRightNode().endShow();
		}
		System.out.println(this.value);
	}
	
	public void deleteNode(String value) {
    
    
		if(this.leftNode!=null&&this.leftNode.value.equals(value)) {
    
    
			this.leftNode=null;
			return;
		}
		if(this.rightNode!=null&&this.rightNode.value.equals(value)) {
    
    
			this.rightNode=null;
			return;
		}
		if(this.leftNode!=null) {
    
    
			this.leftNode.deleteNode(value);
		}
		if(this.rightNode!=null) {
    
    
			this.rightNode.deleteNode(value);
		}
	}
}

Output result:
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_45273552/article/details/109080302