遍历二叉树的神级方法
遍历二叉树的神级方法
题目描述
分别按照二叉树先序,中序和后序打印所有的节点。
输入描述:
第一行输入两个整数 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;
}
遍历二叉树的神级方法相关推荐
- 遍历二叉树的神级方法-Morris遍历【建议收藏】
在前面,我们简单提及过二叉树的遍历方式,有递归和非递归两个版本的遍历.仔细想一想,不管是递归的,还是非递归的遍历,两种版本的遍历都是需要耗费大量的.额外的空间.比如当我们二叉树的高度有100层,那么递 ...
- 遍历二叉树的神级方法(Morris)
给定一棵二叉树的头节点 head,完成二叉树的先序.中序和后序遍历. 如果二叉树的节点数为 N,要求时间复杂度为 O(N),额外空间复杂度为 O(1) 主要思想:莫尔斯遍历,使用空闲右指针,回到后续节 ...
- 遍历二叉树的神级方法(Morris遍历)
题目: 给定一颗二叉树的头节点head,完成二叉树的先序.中序和后序遍历,如果二叉树的节点为N,则要求时间复杂度为O(N),额外空间复杂度为O(1) Morris遍历 代码如下: def getMor ...
- 二叉树的“神级“遍历法
用常量级空间实现二叉树的遍历(morris遍历) 我们在学过的遍历二叉树中通常会借助栈来实现对二叉树的前.中.后序遍历这往往消耗O(n)级别的时间复杂度,而morris遍历仅使用两个指针,消耗掉O(1 ...
- v-for能倒序遍历吗_神级遍历——morris
morris遍历介绍 morris遍历是二叉树遍历算法的超强进阶算法,跟递归.非递归(栈实现)的空间复杂度,morris遍历可以将非递归遍历中的空间复杂度降为O(1).从而实现时间复杂度为O(N),而 ...
- 链表问题15——将搜索二叉树转换成双向链表(方法二)
题目 题目同上一篇文章,即题目将二叉树按照中序顺序转换成双向链表 思路 方法二:利用递归函数,不使用任何容器.时间复杂度为O(N),额外空间复杂度为O(h),h为二d d d df叉树的高度 首先需要 ...
- 遍历二叉树的各种操作(非递归遍历)
先使用先序的方法建立一棵二叉树,然后分别使用递归与非递归的方法实现前序.中序.后序遍历二叉树,并使用了两种方法来进行层次遍历二叉树,一种方法就是使用STL中的queue,另外一种方法就是定义了一个数组 ...
- 彻底理解被称为二叉树神级遍历的莫里斯(Morris)算法
目录 Morris遍历 Morris遍历核心思想 Morris遍历核心代码 Morris遍历过程 先序遍历 中序遍历 后序遍历 二叉树的遍历我们已经介绍过了最常见的递归遍历:用Java描述数据结构之二 ...
- 非递归先序遍历二叉树总结(3种方法)
算法 非递归先序遍历二叉树总结(3种方法) @author:Jingdai @date:2020.12.03 传送门 非递归中序遍历二叉树 非递归后序遍历二叉树 递归先序遍历二叉树非常的简单,但是面试 ...
- php循环方法实现先序、中序、后序遍历二叉树
二叉树是每个节点最多有两个子树的树结构.通常子树被称作"左子树"(left subtree)和"右子树"(right subtree). <?phpnam ...
最新文章
- SAP MM ME29N 试图取消审批报错 - Document has already been outputed(function not possible) -
- eNSP中浮动路由的配置
- python中关于list列表的增删查改操作
- 【python】nuitka封装python
- 学会数据库读写分离、分表分库
- 白话Elasticsearch08-深度探秘搜索技术之基于boost的细粒度搜索条件权重控制
- .html .php .asp,html静态页面中执行php、asp函数代码
- 2020/5/13号单词
- 2014年5月生日会
- pythonweb自动化项目源码下载_python+requests接口自动化完整项目设计源码
- python求幂集_求幂集的算法 - Sethylar的个人页面 - OSCHINA - 中文开源技术交流社区...
- AMOS软件介绍开篇;草堂君给数据分析学习者的几点建议
- java实现列表拖动排序
- Java创建图片并绘图
- 2022年终总结:少年不惧岁月长,彼方尚有荣光在。
- agv调度matlab程序,4款agv调度控制系统应用软件
- 遗传算法求解TSP问题(matlab实现)
- 传感器和变送器的区别
- 移动设备的能源,未来无处不在
- 《阿里巴巴 Java 开发手册 》读书笔记