tree traversal (树的遍历) - 前序遍历 (preorder traversal) - 二叉树的前序遍历

tree traversal (树的遍历) - 前序遍历 (preorder traversal) - 二叉树的前序遍历

1. tree traversal (树的遍历)

1.1 深度优先搜索 (depth-first search,DFS)

我们采用深度作为优先级,从根节点开始一直到达某个确定的叶子节点,然后再返回根节点到达另一个分支。深度优先搜索策略可以根据根节点、左孩子树和右孩子树的相对顺序被细分为前序遍历、中序遍历和后序遍历。

前序遍历 (preorder traversal) - 中序遍历 (inorder traversal) - 后序遍历 (postorder traversal)

1.2 广度优先搜索 - 宽度优先搜索 - 横向优先搜索 (breadth-first search,BFS)

我们按照高度顺序一层一层的访问整棵树,高层次的节点将会比低层次的节点先被访问到。

下图中的节点依照不同的策略遍历,访问的顺序均为 1, 2, 3, 4, 5。宽度优先搜索划分层次为 [[1], [2, 3], [4, 5]]
在这里插入图片描述

递归实现的效率一般比对应的非递归实现低。如果在函数中使用了两个递归调用,效率低下的问题就会变得更为严重。

2. 二叉树的前序遍历

给定一个二叉树,返回它的前序遍历。

输入: [1,null,2,3]  
   1
    \
     2
    /
   3 

输出: [1,2,3]
int* preorderTraversal(struct TreeNode* root, int* returnSize)

输入参数 rootNULL 时,如果 return NULL*returnSize 必须设置为 0

2.1 迭代实现 - 数组模拟栈 (stack) 的操作

从根节点开始,每次迭代弹出当前栈顶元素,并将其孩子节点压入栈中,先压入右孩子再压入左孩子。输出到最终结果的顺序按照 Top -> Bottom 和 Left -> Right,符合前序遍历的顺序。

时间复杂度:访问每个节点恰好一次,时间复杂度为 O(N),其中 N 是节点的个数,即树的大小。
空间复杂度:取决于树的结构,最坏情况存储整棵树,空间复杂度是 O(N)

  1. 设置一个栈,将根节点 push 到栈中。
  2. 循环检测栈是否为空,若不空,则取出栈顶元素,保存其值。
  3. 查看栈顶元素右子节点是否存在,若存在则 push 到栈中。查看栈顶元素左子节点,若存在,则 push 到栈中。
  4. 继续回到 2. 执行,直到栈空。
//============================================================================
// Name        : preorder traversal
// Author      : Yongqiang Cheng
// Version     : Feb 22, 2020
// Copyright   : Copyright (c) 2019 Yongqiang Cheng
// Description : Hello World in C++, Ansi-style
//============================================================================

/*
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

/*
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
	int idx = 0, front = 0;
	struct TreeNode* STACK_DATA[256] = { NULL };
	struct TreeNode* pnode = NULL;
	int *ret = (int*) malloc(256 * sizeof(int));

	*returnSize = 0;

	if ((NULL == root) || (NULL == returnSize))
	{
		return NULL;
	}

	front = -1;
	STACK_DATA[++front] = root;

	while (front >= 0)
	{
		pnode = STACK_DATA[front];
		front--;

		ret[idx] = pnode->val;
		idx++;

		if (NULL != pnode->right)
		{
			STACK_DATA[++front] = pnode->right;
		}

		if (NULL != pnode->left)
		{
			STACK_DATA[++front] = pnode->left;
		}
	}

	*returnSize = idx;

	return ret;
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3. 前序遍历 (preorder traversal)

前序遍历 (preorder traversal) 先沿左侧通路自顶而下访问沿途节点,再自底而上依次遍历这些节点的右子树。

在这里插入图片描述

迭代式前序遍历 (出栈节点以深色示意)
在这里插入图片描述

References

https://leetcode-cn.com/

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值