網上二叉樹線索化的JAVA實現代碼相對較少,今天在中序遍歷的基礎上較小的改變實現了二叉樹中序線索化的遞歸和非遞歸算法,思路非常簡潔,對比非常明顯,相信大家一看就懂。
背景:對於一個n個節點的二叉樹,除了根節點外每個節點都有一個指向父親的引用,因此有n-1個引用,而n個節點總共有2*n個引用,因此還有n+1個引用沒有使用,如果把這些引用分別指向當前節點的前驅或者後繼,則將此二叉樹線索化。線索化後的二叉樹遍歷比較方便,不需要遞歸,效率快。
本文以中序爲例,下面是中序線索化的Java代碼。(其他序列的線索化可以參考我的前一篇文章的二叉樹遍歷進行修改)
package Tree;
import java.util.Stack;
public class ThreadedBinTree {
public static void main(String[] args) {
binTree tree = new binTree();
tree.insertNode(4);
tree.insertNode(3);
tree.insertNode(2);
tree.insertNode(1);
tree.insertNode(3);
tree.insertNode(5);
tree.insertNode(7);
tree.insertNode(6);
System.out.println("midOrder");
tree.midOrderTraverse(tree.getRoot());
System.out.println();
System.out.println("midOderNocursor");
tree.midOrderTraverseNoRecursion(tree.getRoot());
System.out.println();
//---------------------------------------------------------------------------
System.out.println("線索二叉樹,非遞歸");
Node<Integer> headNode = tree.BinTreeThreaded(tree.getRoot());
while(headNode != null){
System.out.print(headNode.value+" ");
headNode = headNode.right;
}
System.out.println();
//************************兩個選擇一個運行***************運行一次改變了Tree的結構************
/*System.out.println("線索二叉樹,遞歸");
Node<Integer> headNode = tree.BinTreeThreadedRecursion(tree.getRoot());
while(headNode != null){
System.out.print(headNode.value+" ");
headNode = headNode.right;
}
System.out.println();*/
//---------------------------------------------------------------------------
System.out.println("end---");
}
}
class Node<E extends Comparable<E>>{
E value;
Node<E> left;
Node<E> right;
Node(){
}
Node(E value){
this.value = value;
}
}
//二叉排序樹
class binTree<E extends Comparable<E>>{
private Node <E> root ;
public binTree() {
// TODO Auto-generated constructor stub
root = null;
}
public Node<E> getRoot(){
return this.root;
}
//插入節點
public void insertNode(E value){
if(root == null){
root = new Node<E>(value);
return;
}
Node<E> currentNode = root;
while(true){
if(value.compareTo(currentNode.value) < 0){
if(currentNode.left == null){
currentNode.left = new Node<E>(value);
return;
}
currentNode = currentNode.left;
}
else{
if(currentNode.right == null){
currentNode.right = new Node<E>(value);
return;
}
currentNode = currentNode.right;
}
}
}
//中序遍歷 遞歸
public void midOrderTraverse(Node<E> root){
if(root.left != null)
midOrderTraverse(root.left);
System.out.print(root.value+" ");
if(root.right != null)
midOrderTraverse(root.right);
}
//中序遍歷 非遞歸
public void midOrderTraverseNoRecursion(Node<E> root) {
Stack<Node<E>> stack = new Stack<Node<E>>();
Node<E> currentNode = root;
while(currentNode!=null || !stack.isEmpty()){
if (currentNode != null) {
stack.push(currentNode);
currentNode = currentNode.left;
}else{
currentNode = stack.pop();
System.out.print(currentNode.value+" ");
currentNode = currentNode.right;
}
}
}
//中序線索化二叉排序樹,非遞歸
public Node<E> BinTreeThreaded(Node<E> root){
Node<E> head ; //標記線索化的頭部,作爲返回值
Node<E> pre =new Node();
head = pre;
//參考中序遍歷
Stack<Node<E>> stack = new Stack<Node<E>>();
Node<E> currentNode = root;
while(currentNode!=null || !stack.isEmpty()){
if (currentNode != null) {
stack.push(currentNode);
currentNode = currentNode.left;
}else{
currentNode = stack.pop();
if(pre.right == null)
pre.right = currentNode; //前一個節點的right指向後一個節點
if(currentNode.left == null)
currentNode.left = pre; //後一個節點的left指向前一個節點
pre = currentNode;
currentNode = currentNode.right;
}
}
return head.right;
}
//中序線索化二叉排序樹,遞歸
public Node<E> BinTreeThreadedRecursion(Node<E> root){
Node<E> head ; //標記線索化的頭部,作爲返回值
Node<E> pre =new Node();
head = pre;
//參考中序遍歷,遞歸
Stack<Node<E>> stack = new Stack<Node<E>>();
Node<E> currentNode = root;
if(root.left != null)
midOrderTraverse(root.left);
if(pre.right == null)
pre.right = root; //前一個節點的right指向後一個節點
if(root.left == null)
root.left = pre; //後一個節點的left指向前一個節點
pre = root;;
if(root.right != null)
midOrderTraverse(root.right);
return head.right;
}
}