您的位置:首页 > 其它

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

2015-08-03 14:34 447 查看
线索二叉树是在普通二叉树模型上建立线索后的树模型,再建立了线索后我们可以在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
代表数的节点,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);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: