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

  1. n个结点的二叉链表中含有n+1 [公式2n-(n-1)=n+1] 个空指针域。利用二叉链表中的空指针域,存放指向该结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索" )
  2. 这种加上了 线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(Threaded BinaryTree)。根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种
  3. 一个结点的前一个结点,称为前驱结点
  4. 一个结点的后一个结点,称为后继结点

将下面的二叉树,进行中序线索二叉树。中序遍历的数列为{8,3, 10,1, 14, 6}
在这里插入图片描述
在这里插入图片描述说明:当线索化二叉树后,Node 节点的属性left 和right ,有如下情况:
left指向的是左子树,也可能是指向的前驱节点.比如①节点left指向的左子树,而面节点的left 指向的就是前驱节点
right指向的是右子树,也可能是指向后继节点,比如①节点right指向的是右子树,而0节点的right指向的是后继节点

遍历线索化二叉树

说明:对前面的中序线索化的二叉树,进行遍历
分析:因为线索化后,各个结点指向有变化,因此原来的遍历方式不能使用,这时需要使用新的方式遍历线索化二叉树,各个节点可以通过线型方式遍历,因此无需使用递归方式,这样也提高了遍历的效率。遍历的次序应当和中序遍历保持一致。

public class ThreadedBinaryTreeDemo {

	public static void main(String[] args) {
	//测试中序线索二叉树功能
		ThreadedBinaryTree binaryTree = new ThreadedBinaryTree();
		HeroNode root = new HeroNode(1,"菲兹");
		HeroNode n2 = new HeroNode(3,"维恩");
		HeroNode n3 = new HeroNode(6,"奎因");
		HeroNode n4 = new HeroNode(8,"潘森");
		HeroNode n5 = new HeroNode(10,"维克多");
		HeroNode n6 = new HeroNode(14,"菲奥娜");
		//简单处理手动创建
		root.setLeft(n2);
		root.setRight(n3);
		n2.setLeft(n4);
		n2.setRight(n5);
		n3.setLeft(n6);
		binaryTree.setRoot(root);
		binaryTree.threadedNodes();
		HeroNode le = n5.getLeft();
		HeroNode ri = n5.getRight();
		System.out.println(le);
		System.out.println(ri);
		
		System.out.println("线索化遍历");
		binaryTree.threadedList();

	}

}

//定义ThreadedBinaryTree二叉树
class ThreadedBinaryTree{
	private HeroNode root;
	//为实现线索化 需要创建给指向当前节点的前驱节点的指针
	//在递归线索化时 pre总是保留前一个节点
	private HeroNode pre = null;
	public HeroNode getRoot() {
		return root;
	}
	public void setRoot(HeroNode root) {
		this.root = root;
	}
	//重载方法
	public void threadedNodes() {
		this.threadedNodes(root);
	}
	//编写对二叉树进行中序线索化的方法
	//node就是当前需要线索化的节点
	public void threadedNodes(HeroNode node) {
		if(node == null) {
			return;
		}
		//1.先线索化左子树
		threadedNodes(node.getLeft());
		//2.线索化当前节点
		//处理当前节点的前驱节点
		if(node.getLeft() == null) {
			//让当前节点的左指针 指向前驱节点
			node.setLeft(pre);
			//修改当前节点的左指针类型 指向前驱节点
			node.setLeftType(1);
		}
		//处理后继节点
		if(pre!=null && pre.getRight() == null) {
			//让前驱节点的右指针指向当前节点
			pre.setRight(node);
			pre.setRightType(1);
		}
		//每处理一个节点后让当前节点是下一个节点的前驱节点
		pre = node;
		
		//3.再线索化右子树
		threadedNodes(node.getRight());
		
	}
	//中序遍历线索化二叉树
	public void threadedList() {
		//定义一个变量 存储当前遍历的节点 从root开始
		HeroNode node = root;
		while(node != null) {
			//先向左遍历
			while(node.getLeftType() == 0) {//表示不是线索化处理后的
				node = node.getLeft();
				
			}
			System.out.println(node);
			//后继节点则一直输出
			while(node.getRightType() == 1) {
				node = node.getRight();
				System.out.println(node);
			}
			node = node.getRight();
		}
	}
	
	
}

//创建HeroNode节点
class HeroNode{
	private int no;
	private String name;
	private HeroNode left;
	private HeroNode right;
	//如果 leftType == 0 表示指向左子树 1表示指向前驱节点
	//如果 rightType == 0 表示指向左子树 1表示指向后继节点
	private int leftType;
	private int rightType;
	
	/**
	 * @return the leftType
	 */
	public int getLeftType() {
		return leftType;
	}
	/**
	 * @param leftType the leftType to set
	 */
	public void setLeftType(int leftType) {
		this.leftType = leftType;
	}
	/**
	 * @return the rightType
	 */
	public int getRightType() {
		return rightType;
	}
	/**
	 * @param rightType the rightType to set
	 */
	public void setRightType(int rightType) {
		this.rightType = rightType;
	}
	public int getNo() {
		return no;
	}
	public HeroNode(int no, String name) {
		super();
		this.no = no;
		this.name = name;
	}
	/**
	 * @param no the no to set
	 */
	public void setNo(int no) {
		this.no = no;
	}
	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}
	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}
	/**
	 * @return the left
	 */
	public HeroNode getLeft() {
		return left;
	}
	/**
	 * @param left the left to set
	 */
	public void setLeft(HeroNode left) {
		this.left = left;
	}
	/**
	 * @return the right
	 */
	public HeroNode getRight() {
		return right;
	}
	/**
	 * @param right the right to set
	 */
	public void setRight(HeroNode right) {
		this.right = right;
	}
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "HeroNode [no=" + no + ", name=" + name + "]";
	}	
}
线索化二叉树是一种增强版的二叉树结构,它通过添加额外的信息(称为线索)来辅助遍历过程,使得从节点到其左、右子节点的导航变得更加直接。主要有三种类型的线索化:前线索化、中线索化和后线索化。 1. **前线索化**(Preorder Dotted Tree):根节点的右孩子线索指向第一个左孩子;若无左孩子,则该线索为空。左孩子的线索则指向其父节点。 2. **中线索化**(Inorder Dotted Tree):对于每个节点,它的左线索总是指向前一个更大的节点,右线索如果存在,是指向其右孩子。如果没有右孩子,那么右线索将指向它的后继节点。 3. **后线索化**(Postorder Dotted Tree):对于每个节点,其左线索指向其左孩子,右线索指向其当前访问的下一个节点(即父节点的左兄弟)。 在C语言中,我们可以定义一个节点结构包含数据以及左右线索,例如: ```c typedef struct Node { int data; struct Node* left, *right; // 子节点指针 struct Node** prev, **next; // 线索指针 } Node; // 中线索化函数示例 void inorder_doubly_link(Node* root) { if (root != NULL) { inorder_doubly_link(root->left); root->prev = &(*root->parent)->right; // 更新左线索 (*root->parent)->right = root; if (root->right != NULL) root->right->prev = &root; // 如果有右孩子,更新右子节点的左线索 inorder_doubly_link(root->right); } } ``` 其中`root->parent`是一个临时变量用于保存当前节点的父节点,以便于设置线索。这只是一个基础的框架,实际操作可能会更复杂一些,包括处理空节点和初始化线索等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值