數據結構線索化二叉樹

我們知道,對於一個n個節點的二叉樹,除了根節點外每個節點都有一個指向父親的引用,因此有n-1個引用,而n個節點總共有2*n個引用,因此還有n+1個引用沒有使用,如果把這些引用分別指向當前節點的前驅或者後繼,則將此二叉樹線索化。線索化後的二叉樹遍歷比較方便,不需要遞歸,效率快。以下使用java語言描述二叉樹的線索化。

二叉樹的節點Node類的代碼如下:

package edu.qc.tree.thread;


public class Node {
private int data;
private Node left;
private boolean leftIsThread;//左孩子是否爲線索
private Node right;
private boolean rightIsThread;//右孩子是否爲線索

public Node(int data){
this.data = data ;
this.left = null ;
this.leftIsThread = false ;
this.right = null ;
this.rightIsThread = false ;
}


public int getData() {
return data;
}


public void setData(int data) {
this.data = data;
}


public Node getLeft() {
return left;
}


public void setLeft(Node left) {
this.left = left;
}


public boolean isLeftIsThread() {
return leftIsThread;
}


public void setLeftIsThread(boolean leftIsThread) {
this.leftIsThread = leftIsThread;
}


public Node getRight() {
return right;
}


public void setRight(Node right) {
this.right = right;
}


public boolean isRightIsThread() {
return rightIsThread;
}


public void setRightIsThread(boolean rightIsThread) {
this.rightIsThread = rightIsThread;
}


@Override
public boolean equals(Object obj) {
if(obj instanceof Node){
Node temp = (Node)obj ;
if(temp.getData() == this.data){
return true ;

}
return false;
}


@Override
public int hashCode() {
return super.hashCode() + this.data ;
}
}


然後具體的線索化二叉樹ThreadTree類的代碼如下:

package edu.qc.tree.thread;


public class ThreadTree {
private Node root;// 跟節點
private int size;// 大小
private Node pre = null ;//線索化的時候保存前驅

public ThreadTree(){
this.root = null ;
this.size = 0 ;
this.pre = null ;
}

public ThreadTree(int[] data){
this.pre = null ;
this.size = data.length ;
this.root = createTree(data , 1) ;//創建二叉樹
}

/**
* 創建二叉樹
* @param data
*/
public Node createTree(int[] data , int index){
if(index > data.length){
return null ;
}
Node node = new Node(data[index-1]) ;
Node left = createTree(data , 2*index) ;
Node right = createTree(data , 2*index+1) ;
node.setLeft(left) ;
node.setRight(right) ;
return node ;
}

/**
* 將以root爲根節點的二叉樹線索化
* @param root
*/
public void inThread(Node root){
if(root != null){
inThread(root.getLeft()) ;//線索化左孩子
if(null == root.getLeft()){//左孩子爲空
root.setLeftIsThread(true) ;//將左孩子設置爲線索
root.setLeft(pre) ;
}
if(pre!=null&&null == pre.getRight()){//右孩子爲空
pre.setRightIsThread(true) ;
pre.setRight(root) ;
}
pre = root ;
inThread(root.getRight()) ;//線索化右孩子
}
}

/**
* 中序遍歷線索二叉樹
* @param root
*/
public void inThreadList(Node root){
if(root != null){
while(root!=null && !root.isLeftIsThread()){//如果左孩子不是線索
root = root.getLeft() ;//
}

do{
System.out.print(root.getData() + ",");
if(root.isRightIsThread()){//如果右孩子是線索
root = root.getRight() ;
}else{//有右孩子
root = root.getRight() ;
while(root!=null && !root.isLeftIsThread()){
root = root.getLeft() ;
}
}
}while(root != null) ; 
}
}

/**
* 先序遍歷遞歸算法
* @param root
*/
public void preList(Node root){
if(root != null){
System.out.print(root.getData() + ",");
preList(root.getLeft()) ;
preList(root.getRight()) ;
}
}

/**
* 中序遍歷
* @param root
*/
public void inList(Node root){
if(root != null){
inList(root.getLeft()) ;
System.out.print(root.getData() + ",");
inList(root.getRight()) ;
}
}


public Node getRoot() {
return root;
}


public void setRoot(Node root) {
this.root = root;
}


public int getSize() {
return size;
}


public void setSize(int size) {
this.size = size;
}


}


然後具體的測試類ThreadTreeTest的代碼如下:

package edu.qc.tree.thread;


public class ThreadTreeTest {
public static void main(String[] args) {
int[] data = {1,2,3,4,5,6,7,8,9,10} ;
ThreadTree tt = new ThreadTree(data) ;//創建普通二叉樹
tt.inList(tt.getRoot()) ;//中序遞歸遍歷二叉樹
System.out.println("");

tt.inThread(tt.getRoot()) ;//採用中序遍歷將二叉樹線索化
tt.inThreadList(tt.getRoot()) ;//中序遍歷線索化二叉樹
}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章