java线索二叉树源代码_中序线索二叉树及相关算法概述(java实现)

中序线索二叉树就是在普通的二叉树上加上了中序线索。

为了节省空间,只增加两个判定位。flagLeft 和 flagRight,当为0时,表示存放的是子女节点。为1时,表示存放的线索。

其中,左节点存放中序前继,右节点存放中序后继。

使用线索,可以有效降低二叉树遍历的复杂度。前序,中序,后序遍历都可不用递归栈实现,而付出的代价只是几个标志位。

建立中序线索二叉树,可以用普通中序遍历实现。用一个pre保存中序前节点,在中序访问时,贯通前后即可。

C++ pre用指针引用,java pre用对象数组保存。因为pre值要保证能在递归过程中传递

最后注意将中序最后一个节点手动赋值。

对于由中序线索二叉树实现树的前序、中序、后序非递归,非栈遍历。之所以能不用栈,是因为中序线索保存了相关信息。

要注意,先找到第一个节点,然后利用中序线索找后继即可。

对于前序,其后继为当前节点右子女走,flagRight为0的第一个节点的右子女。

中序,后继已给出,注意同样要将flagRight为1的的节点一次遍历完。

实际上,画个图模拟一下就清楚了。

建立普通二叉树可根据中序、前序字符串建立的。思想是,根据前序找到根节点,然后根据中序化为左右子树,不断递归。

在划分过程中,左子树和右子树在前序、中序字符串中都是连续的。并且中序和前序字符串长度总是相等。可根据这一点简化划分。

下面给出java代码实现:

package com.company;

/**

* 根据中序及前序建立二叉树

* 根据后序及前序建立二叉树

* 二叉树中序索引化

* Created by zqiguo on 2017/3/8.

*/

public class IndexBinaryTree {

private static class IndexNode{

char value;

IndexNode left;

IndexNode right;

boolean flagLeft;

boolean flagRight;

}

/**

* 建立中序索引二叉树的公用接口,注意手动赋值最后一节点。

* @param root

*/

public static void creatMidIndexTree(IndexNode root){

if (root == null) {

return;

}

IndexNode[] pre = new IndexNode[1];

creatMidIndexTree(root, pre);

pre[0].right = null;

pre[0].flagRight = true;

}

/**

* 建立中序索引,之所以pre 为[]类型,为了在递归中传递值。

* pre保存前一中序节点,这样就足够,注意要手动将最后一个节点右子树赋值。

* 左节点走到底,脑中模拟一遍,就出结果了。

* @param root 根节点

* @param pre IndexNode[], 数组容量为1,用于在递归中保存中序前一节点

*

*/

private static void creatMidIndexTree(IndexNode root, IndexNode[] pre){

if (root == null){

return;

}

creatMidIndexTree(root.left, pre);

if (root.left == null){

root.left = pre[0];

root.flagLeft = true;

}

if (pre[0] != null && pre[0].right == null){

pre[0].right = root;

pre[0].flagRight = true;

}

pre[0] = root;

creatMidIndexTree(root.right, pre);

}

/**

* 根据中序和前序建立二叉树

* @param pre String 前序序列

* @param mid String 中序序列

* @return 根节点

*/

public static IndexNode creatTreeByPreAndMid(String pre, String mid){

IndexNode indexNode = null;

if(pre.length() > 0){

indexNode = new IndexNode();

indexNode.value = pre.charAt(0);

String left = mid.substring(0, mid.indexOf(indexNode.value));

int i = 1;

while (i < pre.length()){

if (left.contains(pre.charAt(i) + "")){

i++;

}else {

break;

}

}

String preLeft = pre.substring(1,i);

String preRight = pre.substring(i,pre.length());

String right = mid.substring(mid.indexOf(indexNode.value)+1, mid.length());

indexNode.left = creatTreeByPreAndMid(preLeft,left);

indexNode.right = creatTreeByPreAndMid(preRight,right);

}

return indexNode;

}

/**

* 根据后序和中序建立二叉树

* @param mid

* @param suf

* @return

*/

public static IndexNode createTreebyMidAndSuf(String mid, String suf){

IndexNode root = null;

if (suf.length() > 0){

root = new IndexNode();

root.value = suf.charAt(suf.length()-1);

String midLeft = mid.substring(0,mid.indexOf(suf.charAt(suf.length()-1)));

String midRight = mid.substring(mid.indexOf(suf.charAt(suf.length()-1))+1, mid.length());

String sufLeft = suf.substring(0,midLeft.length());

String sufRight = suf.substring(midLeft.length(),suf.length()-1);

root.left = createTreebyMidAndSuf(midLeft,sufLeft);

root.right = createTreebyMidAndSuf(midRight,sufRight);

}

return root;

}

/**

* 中序非递归遍历

* @param root

*/

public static void printMidNonStack(IndexNode root){

IndexNode[] stack = new IndexNode[20];

int top = -1;

IndexNode tmp = root;

while (tmp != null || top != -1){

while (tmp != null){

stack[++top] = tmp;

tmp = tmp.left;

}

if (top != -1){

tmp = stack[top--];

System.out.printf(tmp.value + " ");

}

tmp = tmp.right;

}

System.out.println();

}

public static void printMid(IndexNode root){

if (root != null){

printMid(root.left);

System.out.printf(root.value + " ");

printMid(root.right);

}

}

/**

* 前序非递归遍历

* @param root

*/

public static void printPreNonStack(IndexNode root){

IndexNode tmp = root;

IndexNode[] stack = new IndexNode[20];

int top = -1;

while (top != -1 || tmp != null){

if (tmp == null){

tmp = stack[top--];

}else {

System.out.printf(tmp.value + " ");

if (tmp.right != null){

stack[++top] = tmp.right;

}

tmp = tmp.left;

}

}

System.out.println();

}

public static void printPre(IndexNode root){

if (root != null){

System.out.printf(root.value + " ");

printPre(root.left);

printPre(root.right);

}

}

public static void printSuf(IndexNode root){

if (root != null){

printSuf(root.left);

printSuf(root.right);

System.out.printf(root.value + " ");

}

}

/**

* 后序非递归遍历

* @param root

*/

public static void printSufNonStack(IndexNode root){

class FlagIndexNode{

IndexNode indexNode;

boolean right;

}

FlagIndexNode[] stack = new FlagIndexNode[20];

int top = -1;

IndexNode tmp = root;

while (top != -1 || tmp != null){

while (tmp != null){

FlagIndexNode flagIndexNode = new FlagIndexNode();

flagIndexNode.indexNode = tmp;

stack[++top] = flagIndexNode;

tmp = tmp.left;

}

if (stack[top].right == false){

stack[top].right = true;

tmp = stack[top].indexNode.right;

}else {

System.out.printf(stack[top--].indexNode.value + " ");

}

}

System.out.println();

}

/**

* 使用中序索引二叉树来实现前序遍历。不用栈。

* 方法要点在于找出节点的前序后继。节点的前序后继就是节点中序后继标志不为TRUE的第一个节点的右子树。

* 画一个树图示意一下,就明白了。

* @param root

*/

public static void printPreOrderUseIndex(IndexNode root){

IndexNode tmp = root;

while (tmp != null){

while (tmp.flagLeft != true) {

System.out.printf(tmp.value + " ");

tmp = tmp.left;

}

System.out.printf(tmp.value + " ");

if (tmp.flagRight != true){

tmp = tmp.right;

}else {

while (tmp.flagRight == true && tmp.right != null){

tmp = tmp.right;

}

tmp = tmp.right;

}

}

System.out.println();

}

/**

* Use middle indexed binary tree to print middle traversal order.

* @param root the root of tree

*/

public static void printMidOrderUseIndex(IndexNode root){

IndexNode tmp = root;

while (tmp != null){

while (tmp.flagLeft != true){

tmp = tmp.left;

}

System.out.printf(tmp.value + " ");

while (tmp.flagRight == true && tmp.right != null){

tmp = tmp.right;

System.out.printf(tmp.value + " ");

}

tmp = tmp.right;

}

}

public static void main(String[] args){

String pre = "ABDGCEF";

String mid = "BGDACEF";

String suf = "GDBFECA";

IndexNode root = creatTreeByPreAndMid(pre,mid);

IndexNode root2 = createTreebyMidAndSuf(mid,suf);

printMid(root);

System.out.println();

printMidNonStack(root);

printMid(root2);

System.out.println();

printMidNonStack(root2);

System.out.println();

printPre(root);

System.out.println();

printPreNonStack(root2);

printPre(root2);

System.out.println();

System.out.println();

printSuf(root);

System.out.println();

printSufNonStack(root);

System.out.println();

System.out.println();

printPreNonStack(root);

printMidNonStack(root);

creatMidIndexTree(root);

printPreOrderUseIndex(root);

printMidOrderUseIndex(root);

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值