三种遍历下,二叉树的下一个结点

该博客探讨了在三种不同的遍历方法(前序、中序和后序)下,如何找到给定二叉树节点的中序遍历顺序的下一个节点。内容涉及如何利用树的结构,包括父节点指针,来有效地找到目标节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

	/*
	 * 中序遍历 思路: 
	 * (1) 若该节点存在右子树:则下一个节点为右子树最左子节点(如图节点 B ) 
	 * (2) 若该节点不存在右子树:这时分两种情况:
	 * 2.1 该节点为父节点的左子节点,则下一个节点为其父节点(如图节点 D ) 
	 * 2.2该节点为父节点的右子节点,则沿着父节点向上遍历,直到找到一个节点的父节点的左子节点为该节点, 则该节点的父节点下一个节点(如图节点 I,沿着父节点一直向上查找找到 B ( B 为其父节点的左子节点),则 B 的父节点 A 为下一个节点)。
	 */
	public TreeLinkNode GetNext(TreeLinkNode pNode) {
		// 该节点为空节点
		if (pNode == null) {
			return null;
		}
		// 该节点有右子树,下一节点为右子树最左节点
		if (pNode.right != null) {
			// 指向右子树的根节点
			pNode = pNode.right;
			// 查找最左子树
			while (pNode.left != null) {
				pNode = pNode.left;
			}
			return pNode;
		}
		// 该节点无右子树,
		while (pNode.next != null) {
			TreeLinkNode proot = pNode.next;
			// 该节点是父节点的左子节点,返回父节点
			if (proot.left == pNode) {
				return proot;
			}
			// 改节点是父节点的右子树,向上继续找到直到该节点是父节点的左子节点
			if (proot.right == pNode) {
				pNode = proot;
			}
		}
		// 直到为根节点时,则返回null
		return null;
 
	}
 
	/**
	 * 前序遍历 
	 * 1.只有根节点时,节点为空时(节点A) 
	 * 2.有左子节点时,直接返回左子节点 
	 * 3.无左子节点时,向上遍历父节点知道得到右子节点
	 * 这里有一个特殊情况,就是当该节点本身就是右子节点时,需要保存自身,在往上遍历
	 * 
	 * */
	public TreeLinkNode GetNextbyFirst(TreeLinkNode pNode) {
		if (pNode == null) {
			return null;
		}
		// 只有根节点的情况(节点A)
		if (pNode.next == null && pNode.left == null && pNode.right == null) {
			return null;
		}
		// 如果有左子节点,直接返回(节点BCE)
		if (pNode.left != null) {
			return pNode.left;
		}
		// 标记当前节点
		TreeLinkNode p = pNode;
		// 当前节点无左子节点时,
		while (pNode != null) {
			// 如果有右子节点,则返回右子节点,否则往上找父节点的兄弟
			if (pNode.right != p && pNode.right != null) {
				return pNode.right;
			} else {
				p = pNode;
				pNode = pNode.next;
			}
		}
		return null;
	}
 
	/**
	 * 后序遍历--左右根
	 * 
	 * 
	 * 
	 * */
	public TreeLinkNode GetNextbyLast(TreeLinkNode pNode) {
		if (pNode == null || pNode.next == null) {
			return null;
		}
		// 该节点为右子树上的节点,且该节点无子节点,则后序遍历的下一个节点是该节点的父节点
		if (pNode.left == null && pNode.right == null) {
			// 该节点为父节点的左子节点
			if (pNode.next.left == pNode) {
				// 该节点无右兄弟
				if (pNode.next.right == null) {
					return pNode.next;
				}
				// 该节点有右兄弟子树
				else {
					// 找到最左子节点
					pNode = pNode.next.right;
					while (pNode != null) {
						// 左子节点不为空
						if (pNode.left != null) {
							pNode = pNode.left;
						}
						// 左子节点为空,右子节点不为空
						else if (pNode.right != null) {
							pNode = pNode.right;
						}
						// 左右子节点都为空
						else {
							return pNode;
						}
					}
				}
			}
 
		}
		// 该节点为父节点的左子节点
		if (pNode.left != null && pNode.right != null
				&& pNode.next.left == pNode) {
			// 该节点无右兄弟
			if (pNode.next.right == null) {
				return pNode.next;
			}
			// 该节点有右兄弟子树
			else {
				// 找到最左子节点
				pNode = pNode.next.right;
				while (pNode != null) {
					// 左子节点不为空
					if (pNode.left != null) {
						pNode = pNode.left;
					}
					// 左子节点为空,右子节点不为空
					else if (pNode.right != null) {
						pNode = pNode.right;
					}
					// 左右子节点都为空
					else {
						return pNode;
					}
				}
			}
		}
		// 该节点为父节点的右子节点,则返回父节点,节点I,
		if (pNode.next.right == pNode) {
			return pNode.next;
		}
		return pNode;
 
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值