zoukankan      html  css  js  c++  java
  • JAVA递归实现线索化二叉树

    JAVA递归实现线索化二叉树

    基础理论

    首先,二叉树递归遍历分为先序遍历、中序遍历和后序遍历。

    先序遍历为:根节点+左子树+右子树

    中序遍历为:左子树+根节点+右子树

    后序遍历为:左子树+右子树+根节点

    (只要记住根节点在哪里就是什么遍历,且都是先左再右)

    线索化

    现在有这么一棵二叉树,它的数据结构由左节点+权+右节点构成。

    mark

    可以看到4,5,6,7这几个节点的左右节点空间被浪费了。因此,线索化是指有效利用这些空间。

    中序遍历的顺序为:4 2 5 1 6 3 7

    现在引入前驱节点以及后继节点。

    前驱节点:线索化二叉树时,一个节点的前一个节点

    后继节点:线索化二叉树时,一个节点的后一个节点

    (例如下图:根据中序遍历,5的前驱节点是2 , 5的后继节点是1)

    mark

    (中序遍历)实现线索化二叉树

    定义数据结构ThreadedNode

    	//节点的权
    	int value;
    	//左儿子
    	ThreadedNode leftNode;
    	//右儿子
    	ThreadedNode rightNode;
    	//标识指针类型,其中0,1分别表示有无线索化,默认为0
    	int leftType;
    	int rightType;
    

    中序遍历

    //中序遍历
    public void midShow() {
       //左子节点
       if(leftNode!=null) {
          leftNode.midShow();
       }
       //当前节点
       System.out.println(value);
       //右子节点
       if(rightNode!=null) {
          rightNode.midShow();
       }
    }
    

    这里使用递归的方式来实现。我们先把问题简单化,只看红圈的部分,如下图

    mark

    定义一个节点pre用来存储当前节点,类似指针。

    从根节点1开始递归,如果当前节点为空,返回,到4,此时4的前驱结点为null,结点5的前驱结点为2

    遍历到5的时候指向前驱结点2,前驱结点2为上一层递归的指针,因此指向它的前驱结点就行,再把左指针类型置为1

    如果当前节点的前驱结点pre的右指针为null,则将它设置为当前节点,此时即4的后继结点为2,并将右指针类型置为1

    每处理一个节点,当前节点是下一个节点的前驱节点

    线索化二叉树ThreadedBinaryTree

    	
    	//中序线索化二叉树
    	public void threadNodes() {
    		threadNodes(root);
    	}
    	
    	public void threadNodes(ThreadedNode node) {
    		//当前节点如果为null,直接返回
    		if(node==null) {
    			return;
    		}
    		//处理前驱节点
    		if(node.leftNode==null){
    			//让当前节点的左指针指向前驱节点
    			node.leftNode=pre;
    			//改变当前节点左指针的类型
    			node.leftType=1;
    		}
    		//处理前驱的右指针,如果前驱节点的右指针是null(没有指下右子树)
    		if(pre!=null&&pre.rightNode==null) {
    			//让前驱节点的右指针指向当前节点
    			pre.rightNode=node;
    			//改变前驱节点的右指针类型
    			pre.rightType=1;
    		}
    		//每处理一个节点,当前节点是下一个节点的前驱节点
    		pre=node;
    	}
    

    现在再把上面这段代码按照中序遍历的方式放在中间,进行递归

    		//当前节点如果为null,直接返回
    		if(node==null) {
    			return;
    		}
    		//处理左子树
    		threadNodes(node.leftNode);
    //----------------------------------------------------------
    		//处理前驱节点
    		if(node.leftNode==null){
    			//让当前节点的左指针指向前驱节点
    			node.leftNode=pre;
    			//改变当前节点左指针的类型
    			node.leftType=1;
    		}
    		//处理前驱的右指针,如果前驱节点的右指针是null(没有指下右子树)
    		if(pre!=null&&pre.rightNode==null) {
    			//让前驱节点的右指针指向当前节点
    			pre.rightNode=node;
    			//改变前驱节点的右指针类型
    			pre.rightType=1;
    		}
    		//每处理一个节点,当前节点是下一个节点的前驱节点
    		pre=node;
    //-----------------------------------------------------------
    		//处理右子树
    		threadNodes(node.rightNode);
    	}
    

    现在编写测试方法

    package demo7;
    
    public class TestThreadedBinaryTree {
    
    	public static void main(String[] args) {
    		//创建一颗树
    		ThreadedBinaryTree binTree = new ThreadedBinaryTree();
    		//创建一个根节点
    		ThreadedNode root = new ThreadedNode(1);
    		//把根节点赋给树
    		binTree.setRoot(root);
    		//创建一个左节点
    		ThreadedNode rootL = new ThreadedNode(2);
    		//把新创建的节点设置为根节点的子节点
    		root.setLeftNode(rootL);
    		//创建一个右节点
    		ThreadedNode rootR = new ThreadedNode(3);
    		//把新创建的节点设置为根节点的子节点
    		root.setRightNode(rootR);
    		//为第二层的左节点创建两个子节点
    		rootL.setLeftNode(new ThreadedNode(4));
    		ThreadedNode fiveNode = new ThreadedNode(5);
    		rootL.setRightNode(fiveNode);
    		//为第二层的右节点创建两个子节点
    		rootR.setLeftNode(new ThreadedNode(6));
    		rootR.setRightNode(new ThreadedNode(7));
    		//中序遍历树
    		binTree.midShow();
    		System.out.println("===============");
    		//中前线索化二叉树
    		binTree.threadNodes();
    		binTree.threadIterate();
    	}
    
    }
    
    
  • 相关阅读:
    VUEX
    使用element框架 增加router路由
    VUE目录
    elementUI 创建
    VUE组件(父子组件)
    VUE操作DOM获取HTML、删除HTML、插入HTML
    VUE网络交互axios(网络请求库)
    VUE 或者JS 常用数据类型及方法:字符串、数组、对象
    VUE实际案例--计数器(商城数量加减)
    VUE学习 --数据类型、el挂点、指令等
  • 原文地址:https://www.cnblogs.com/senup/p/12417117.html
Copyright © 2011-2022 走看看