遍历二叉树的神级方法

题目描述

分别按照二叉树先序,中序和后序打印所有的节点。

输入描述:

第一行输入两个整数 n 和 root,n 表示二叉树的总节点个数,root 表示二叉树的根节点。
以下 n 行每行三个整数 fa,lch,rch,表示 fa 的左儿子为 lch,右儿子为 rch。(如果 lch 为 0 则表示 fa 没有左儿子,rch同理)

输出描述:

输出三行分别表示二叉树的前序,中序和后序遍历。

要求:

时间复杂度为O(N)O(N)O(N),额外的空间复杂度为O(1)O(1)O(1)

示例1
输入
3 1
1 2 3
2 0 0
3 0 0
输出
1 2 3
2 1 3
2 3 1
备注:

1≤n≤1061 \leq n \leq 10^61≤n≤106

1≤fa,lch,rch,root≤n1 \leq fa,lch,rch,root \leq n1≤fa,lch,rch,root≤n


题解:

先序遍历、中序遍历和后续遍历没什么好说的,但是这题要求额外的空间的复杂度为O(1)O(1)O(1),无论是递归还是非递归,我们需要的额外空间复杂度为O(h)O(h)O(h),h 为树的高度。究其原因:因为每个节点都有指向孩子节点的指针,所以从上层到下层容易,但是没有指向父节点的指针,所以从下层到上层需要用栈结构辅助完成。

Moris遍历的实质是就是避免使用栈结构,而是让下层到上层有指针,具体就是让底层节点指向 null 的空闲指针指向上层的某个节点,从而完成下层到上层的移动。

具体参考:Moris遍历

代码:
#include <cstdio>
#include <unordered_map>using namespace std;struct BST {int val;BST *lch, *rch;BST (int v) : val(v), lch(NULL), rch(NULL) {}
};BST *createTree() {int n, rt;int fa, lch, rch;scanf("%d%d", &n, &rt);BST *tmp = NULL, *root = NULL;unordered_map<int, BST*> hash;while (n--) {scanf("%d%d%d", &fa, &lch, &rch);if (!hash.count(fa)) {tmp = new BST(fa);hash[fa] = tmp;}if (lch && !hash.count(lch)) {tmp = new BST(lch);hash[lch] = tmp;}if (rch && !hash.count(rch)) {tmp = new BST(rch);hash[rch] = tmp;}if (lch) hash[fa]->lch = hash[lch];if (rch) hash[fa]->rch = hash[rch];}return hash[rt];
}void morisPreOrder(BST *root) {if (!root) return;BST *cur1 = root, *cur2 = NULL;while (cur1) {cur2 = cur1->lch;if (cur2) {while (cur2->rch && cur2->rch != cur1) cur2 = cur2->rch;if (!cur2->rch) {cur2->rch = cur1;printf("%d ", cur1->val);cur1 = cur1->lch;continue;} else {cur2->rch = NULL;}} else {printf("%d ", cur1->val);}cur1 = cur1->rch;}puts("");
}void morisInOrder(BST *root) {if (!root) return;BST *cur1 = root, *cur2 = NULL;while (cur1) {cur2 = cur1->lch;if (cur2) {while (cur2->rch && cur2->rch != cur1) cur2 = cur2->rch;if (!cur2->rch) {cur2->rch = cur1;cur1 = cur1->lch;continue;} else {cur2->rch = NULL;}}printf("%d ", cur1->val);cur1 = cur1->rch;}puts("");
}BST *reverseEdge(BST *root) {BST *pre = NULL, *tmp = NULL;while (root) {tmp = root->rch;root->rch = pre;pre = root;root = tmp;}return pre;
}void printEdge(BST *root) {BST *tail = reverseEdge(root);BST *p = tail;while (p) {printf("%d ", p->val);p = p->rch;}reverseEdge(tail);
}void morisPost(BST *root) {if (!root) return;BST *cur1 = root, *cur2 = NULL;while (cur1) {cur2 = cur1->lch;if (cur2) {while (cur2->rch && cur2->rch != cur1) cur2 = cur2->rch;if (!cur2->rch) {cur2->rch = cur1;cur1 = cur1->lch;continue;} else {cur2->rch = NULL;printEdge(cur1->lch);}}cur1 = cur1->rch;}printEdge(root);puts("");
}int main(void) {BST *root = createTree();morisPreOrder(root);morisInOrder(root);morisPost(root);return 0;
}

遍历二叉树的神级方法相关推荐

  1. 遍历二叉树的神级方法-Morris遍历【建议收藏】

    在前面,我们简单提及过二叉树的遍历方式,有递归和非递归两个版本的遍历.仔细想一想,不管是递归的,还是非递归的遍历,两种版本的遍历都是需要耗费大量的.额外的空间.比如当我们二叉树的高度有100层,那么递 ...

  2. 遍历二叉树的神级方法(Morris)

    给定一棵二叉树的头节点 head,完成二叉树的先序.中序和后序遍历. 如果二叉树的节点数为 N,要求时间复杂度为 O(N),额外空间复杂度为 O(1) 主要思想:莫尔斯遍历,使用空闲右指针,回到后续节 ...

  3. 遍历二叉树的神级方法(Morris遍历)

    题目: 给定一颗二叉树的头节点head,完成二叉树的先序.中序和后序遍历,如果二叉树的节点为N,则要求时间复杂度为O(N),额外空间复杂度为O(1) Morris遍历 代码如下: def getMor ...

  4. 二叉树的“神级“遍历法

    用常量级空间实现二叉树的遍历(morris遍历) 我们在学过的遍历二叉树中通常会借助栈来实现对二叉树的前.中.后序遍历这往往消耗O(n)级别的时间复杂度,而morris遍历仅使用两个指针,消耗掉O(1 ...

  5. v-for能倒序遍历吗_神级遍历——morris

    morris遍历介绍 morris遍历是二叉树遍历算法的超强进阶算法,跟递归.非递归(栈实现)的空间复杂度,morris遍历可以将非递归遍历中的空间复杂度降为O(1).从而实现时间复杂度为O(N),而 ...

  6. 链表问题15——将搜索二叉树转换成双向链表(方法二)

    题目 题目同上一篇文章,即题目将二叉树按照中序顺序转换成双向链表 思路 方法二:利用递归函数,不使用任何容器.时间复杂度为O(N),额外空间复杂度为O(h),h为二d d d df叉树的高度 首先需要 ...

  7. 遍历二叉树的各种操作(非递归遍历)

    先使用先序的方法建立一棵二叉树,然后分别使用递归与非递归的方法实现前序.中序.后序遍历二叉树,并使用了两种方法来进行层次遍历二叉树,一种方法就是使用STL中的queue,另外一种方法就是定义了一个数组 ...

  8. 彻底理解被称为二叉树神级遍历的莫里斯(Morris)算法

    目录 Morris遍历 Morris遍历核心思想 Morris遍历核心代码 Morris遍历过程 先序遍历 中序遍历 后序遍历 二叉树的遍历我们已经介绍过了最常见的递归遍历:用Java描述数据结构之二 ...

  9. 非递归先序遍历二叉树总结(3种方法)

    算法 非递归先序遍历二叉树总结(3种方法) @author:Jingdai @date:2020.12.03 传送门 非递归中序遍历二叉树 非递归后序遍历二叉树 递归先序遍历二叉树非常的简单,但是面试 ...

  10. php循环方法实现先序、中序、后序遍历二叉树

    二叉树是每个节点最多有两个子树的树结构.通常子树被称作"左子树"(left subtree)和"右子树"(right subtree). <?phpnam ...

最新文章

  1. SAP MM ME29N 试图取消审批报错 - Document has already been outputed(function not possible) -
  2. eNSP中浮动路由的配置
  3. python中关于list列表的增删查改操作
  4. 【python】nuitka封装python
  5. 学会数据库读写分离、分表分库
  6. 白话Elasticsearch08-深度探秘搜索技术之基于boost的细粒度搜索条件权重控制
  7. .html .php .asp,html静态页面中执行php、asp函数代码
  8. 2020/5/13号单词
  9. 2014年5月生日会
  10. pythonweb自动化项目源码下载_python+requests接口自动化完整项目设计源码
  11. python求幂集_求幂集的算法 - Sethylar的个人页面 - OSCHINA - 中文开源技术交流社区...
  12. AMOS软件介绍开篇;草堂君给数据分析学习者的几点建议
  13. java实现列表拖动排序
  14. Java创建图片并绘图
  15. 2022年终总结:少年不惧岁月长,彼方尚有荣光在。
  16. agv调度matlab程序,4款agv调度控制系统应用软件
  17. 遗传算法求解TSP问题(matlab实现)
  18. 传感器和变送器的区别
  19. 移动设备的能源,未来无处不在
  20. 《阿里巴巴 Java 开发手册 》读书笔记

热门文章

  1. Firefox火狐浏览器插件大全
  2. 「面试必背」Elasticsearch面试题(收藏)
  3. 能否用一种语言来培养编程思维以及养成世界观
  4. Winner-Take-All Autoencoders ( 赢者通吃自编码器)
  5. [VBA学习]关于Formula以及数字格式的问题
  6. 一个移动开发老码农的书单
  7. 红米手机2进入开发者模式的方法
  8. React 事件处理
  9. 1 is not JSON serializable的解决方案
  10. Vue项目-手机app瑞幸咖啡详解(全网最细) 从脚手架搭建到前后端数据交互(二)