二叉树中序遍历
中序遍历
顺序为:左子树->跟节点->右子树
先遍历左子树,然后遍历跟节点,最后遍历右子树,以此轮推,直到遍历完所有节点。
如上二叉树中序遍历结果为:1 2 3 4 5 6 7 8 9
一件很巧合的事情,遍历结果为一组已排序的序列,熟悉二叉搜索树的同学会发现,上边的二叉树其实是符合搜索二叉树。
二叉搜索树特征如下:
1.每个节点的值大于其左子树上所有节点的值(如果左子树不为空)
2.每个节点的值小于其右子树上所有节点的值(如果右子树不为空)
3.所有左子树和右子树自身也必须是二叉搜索树
检查如上二叉树结构,完全符合二叉树的所有特征,所以可以判定如上二叉树是一颗二叉搜索树。当把二叉树所有节点从左到右依次映射到一个序列中,所得到的序列即为一个按照升序排列的序列。
可以使用此方法来验证一颗二叉树,是否是一个二叉搜索树。
下面来说说二叉搜索树中序遍历逻辑:
中序遍历的顺序为:左子树->跟节点->右子树
要求如下:
1:每个节点的值只获取一次
2:如果节点有左子树,执行 1 之前要先获取左子树所有节点的值
3:执行 1 之后,如果节点有右子树,然后获取节点右树所有节点的值
4:所有节点值的获取,要遵守 1、2、3 条
实现方案有两种
一:递归实现
二:迭代实现
// 节点定义如下
public class TreeNode
{
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val = 0, TreeNode left = null, TreeNode right = null)
{
this.val = val;
this.left = left;
this.right = right;
}
}
递归实现如下
public IList<int> InorderTraversal(TreeNode root)
{
// 集合存储访问节点的值
IList<int> list = new List<int>();
// 调用递归函数
InorderTraversal(root, list);
return list;
}
public void InorderTraversal(TreeNode node, IList<int> list)
{
if (null == node)
{
return;
}
// 递归调用左子树
InorderTraversal(node.left, list);
// 将节点值存储到集合中
list.Add(node.val);
// 递归访问右子树
InorderTraversal(node.right, list);
}
迭代实现如下
//迭代实现
public IList<int> InorderTraversal2(TreeNode root)
{
// 集合存储访问节点的值
IList<int> list = new List<int>();
// 以栈结构(先进后出)来构建节点访问次序
Stack<TreeNode> stack = new Stack<TreeNode>();
// 先将跟节点入栈
stack.Push(root);
// 新建临时节点从 root 开始
TreeNode node = root;
while (stack.Count > 0)
{
// 迭代直到得到最深的左子树
while (null != node && (null != node.left))
{
stack.Push(node.left);
node = node.left;
}
// 节点出栈
node = stack.Pop();
if (null != node)
{
// 将节点的值存入集合中
list.Add(node.val);
// 如果有子树不为空,则将右子树入栈
if (null != node.right)
{
stack.Push(node.right);
}
// 令节点等于其右子树,此时右子树可以为空
node = node.right;
}
}
return list;
}
至此二叉树中序遍历的原理以及实现均已奉上