二叉树的遍历(递归,迭代,Morris遍历)
二叉树的三种遍历方法:
先序,中序,后序,这三种遍历方式每一个都可以用递归,迭代,Morris三种形式实现,其中Morris效率最高,空间复杂度为O(1)。
主要参考博客:
Morris Traversal方法遍历二叉树(非递归,不用栈,O(1)空间)
#include <iostream>
#include <vector>
#include <stack>
using namespace std; struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int _val) :val(_val){
left = NULL; right = NULL;
} }; TreeNode* BuildTree()
{
TreeNode* root = new TreeNode(6); int array[] = { 2, 7, 1, 4, 9, 3, 5, 8 };
vector<TreeNode*> list;
//cout << sizeof(array) / sizeof(array[0]) << endl;
for (size_t i = 0; i <sizeof(array)/sizeof(array[0]); i++)
{
TreeNode* t = new TreeNode(array[i]);
list.push_back(t);
}
root->left = list[0];
root->right = list[1];
list[0]->left = list[2];
list[0]->right = list[3];
list[1]->right = list[4];
list[3]->left = list[5];
list[3]->right = list[6];
list[4]->left = list[7]; return root;
} void preorderRecursive(TreeNode* t)
{
if (t == NULL)
return;
cout << t->val << " ";
preorderRecursive(t->left);
preorderRecursive(t->right); } void preorderIterative(TreeNode* root)
{
if (root == NULL)
return;
stack<TreeNode*> stk;
TreeNode* cur = root;
while (cur || !stk.empty())
{
while (cur)
{
cout << cur->val << " ";
stk.push(cur);
cur = cur->left;
}
if (!stk.empty())
{
cur = stk.top();
stk.pop();
cur = cur->right;
}
} } void preorderMorris(TreeNode* root)
{
if (root == NULL)
return;
TreeNode* cur = root;
TreeNode* pre = NULL;//前驱节点
while (cur)
{
if (cur->left == NULL){
cout << cur->val << " ";
cur = cur->right;
}
else{
pre = cur->left;
while (pre->right != NULL && pre->right != cur)
pre = pre->right;
if (pre->right == NULL){
cout << cur->val << " ";
pre->right = cur;
cur = cur->left;
}
else{
pre->right = NULL;
cur = cur->right;
}
}
}
} void inorderRecursive(TreeNode* root)
{
if (root == NULL)
return;
inorderRecursive(root->left);
cout << root->val << " ";
inorderRecursive(root->right);
} void inorderIterative(TreeNode* root)
{
stack<TreeNode* > stk;
TreeNode* cur = root;
while (cur || !stk.empty())
{
while (cur){
stk.push(cur);
cur = cur->left;
}
if (!stk.empty()){ cur = stk.top();
cout << cur->val << " ";
stk.pop();
cur = cur->right;
} }
} void inorderMorris(TreeNode* root)
{
TreeNode* cur = root;
TreeNode* pre = NULL; //前驱节点
while (cur)
{
if (cur->left == NULL){
cout << cur->val << " ";
cur = cur->right;
}
else{
pre = cur->left;
while (pre->right != NULL && pre->right != cur)
pre = pre->right;
if (pre->right == NULL){
pre -> right = cur;
cur = cur->left;
}
else{
cout << cur->val << " ";
pre->right = NULL;
cur = cur->right;
}
}
}
} void postorderRecursive(TreeNode* root)
{
if (root == NULL)
return;
postorderRecursive(root->left);
postorderRecursive(root->right);
cout << root->val << " "; } void postorderIterative(TreeNode* root)
{
stack<TreeNode*> stk;
TreeNode* cur = root;
TreeNode* pre = NULL;
while (cur || !stk.empty()){
while (cur){
stk.push(cur);
cur = cur->left;
}
if (!stk.empty()){
cur = stk.top();
if (cur->right != NULL && cur->right != pre){
cur = cur->right;
}
else{
cout << cur->val<<" ";
pre = cur;
stk.pop();
cur = NULL;
}
}
}
} void reverse(TreeNode *begin, TreeNode *end) {
if (begin == end)
return;
TreeNode *pre = begin;
TreeNode *cur = begin->right;
TreeNode *next;
while (pre != end) {
TreeNode* temp = cur->right;
cur->right = pre;
pre = cur;
cur = temp;
}
} void traversalReversal(TreeNode *begin, TreeNode *end) {
reverse(begin, end);
TreeNode *it = end;
while (true) {
cout << it->val << " ";
if (it == begin)
break;
it = it->right;
}
reverse(end, begin);
} void postorderMorris(TreeNode *root) {
if (!root)
return;
TreeNode dump(0);
dump.left = root;
TreeNode *cur = &dump;
TreeNode *pre = NULL;
while (cur) {
if (cur->left == NULL) {
cur = cur->right;
}
else {
pre = cur->left;
while (pre->right != NULL && pre->right != cur)
pre = pre->right;
if (pre->right == NULL) {
pre->right = cur;
cur = cur->left;
}
else {
traversalReversal(cur->left, pre);
pre->right = NULL;
cur = cur->right;
}
}
}
} int main(void)
{ TreeNode* root = BuildTree();
cout << "----------Preorder Recursive--------------" << endl;
preorderRecursive(root);
cout <<endl;
cout << "----------Preorder Iterative---------------" << endl;
preorderIterative(root);
cout << endl;
cout << "----------Preorder Morris---------------" << endl;
preorderMorris(root);
cout << endl;
cout << endl; cout << "----------Inorder Recursive--------------" << endl;
inorderRecursive(root);
cout << endl;
cout << "----------Inorder Iterative--------------" << endl;
inorderIterative(root);
cout << endl;
cout << "----------Inorder Morris-----------------" << endl;
inorderMorris(root);
cout << endl;
cout << endl; cout << "----------Postorder Recursive--------------" << endl;
postorderRecursive(root);
cout << endl;
cout << "----------Postorder Iterative--------------" << endl;
postorderIterative(root);
cout << endl;
cout << "----------Postorder Morris-----------------" << endl;
postorderMorris(root);
cout << endl; }
二叉树的遍历(递归,迭代,Morris遍历)的更多相关文章
- 二叉树的建立&&前中后遍历(递归实现)&&层次遍历
下面代码包含了二叉树的建立过程,以及三种遍历方法了递归实现,代码中还利用队列实现了层次遍历. import java.util.LinkedList; import java.util.Queue; ...
- LeetCode:二叉树的非递归中序遍历
第一次动手写二叉树的,有点小激动,64行的if花了点时间,上传leetcode一次点亮~~~ /* inorder traversal binary tree */ #include <stdi ...
- Python实现二叉树的非递归先序遍历
思路: 1. 使用列表保存结果: 2. 使用栈(列表实现)存储结点: 3. 当根结点存在,保存结果,根结点入栈: 4. 将根结点指向左子树: 5. 根结点不存在,栈顶元素出栈,并将根结点指向栈顶元素的 ...
- Python实现二叉树的非递归中序遍历
思路: 1. 使用一个栈保存结点(列表实现): 2. 如果结点存在,入栈,然后将当前指针指向左子树,直到为空: 3. 当前结点不存在,则出栈栈顶元素,并把当前指针指向栈顶元素的右子树: 4. 栈不为空 ...
- Morris 遍历实现二叉树的遍历
Morris 遍历实现二叉树的遍历 作者:Grey 原文地址: 博客园:Morris 遍历实现二叉树的遍历 CSDN:Morris 遍历实现二叉树的遍历 说明 Morris 遍历可以实现二叉树的先,中 ...
- 经典算法 Morris遍历
内容: 1.什么是morris遍历 2.morris遍历规则与过程 3.先序及中序 4.后序 5.morris遍历时间复杂度分析 1.什么是morris遍历 关于二叉树先序.中序.后序遍历的递归和非递 ...
- 二叉树的遍历(递归,迭代,Morris遍历)
二叉树的遍历: 先序,中序,后序: 二叉树的遍历有三种常见的方法, 最简单的实现就是递归调用, 另外就是飞递归的迭代调用, 最后还有O(1)空间的morris遍历: 二叉树的结构定义: struct ...
- [转载]Morris Traversal方法遍历二叉树(非递归,不用栈,O(1)空间)
本文主要解决一个问题,如何实现二叉树的前中后序遍历,有两个要求: 1. O(1)空间复杂度,即只能使用常数空间: 2. 二叉树的形状不能被破坏(中间过程允许改变其形状). 通常,实现二叉树的前序(pr ...
- Morris Traversal方法遍历二叉树(非递归,不用栈,O(1)空间)——无非是在传统遍历过程中修改叶子结点加入后继结点信息(传统是stack记录),然后再删除恢复
先看看线索二叉树 n个结点的二叉链表中含有n+1(2n-(n-1)=n+1)个空指针域.利用二叉链表中的空指针域,存放指向结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索 ...
随机推荐
- iOS开发之多线程技术
本篇争取一篇讲清讲透,依然将通过四大方面清晰的对iOS开发中多线程的用法进行详尽的讲解: 一.什么是多线程 1)多线程执行原理 2)线程与进程 3)多线程的优缺点 二.我们为什么要用多线程编程技术 三 ...
- 使用CSS3滤镜让图片反转颜色
CSS提供的滤镜也是一大亮点,我一直痴迷其中,有些滤镜的效果很有用,可是有些的滤镜效果可能只是为了玩玩儿,CSS常见的滤镜有这些:grayscale, blur, sepia,所有常见的过滤器.但是如 ...
- git之二
1.什么是版本库? 版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改.删除,Git都能跟踪,以便任何时刻都可以追踪历史 ...
- #winhec# 开发人员刷屏看点 (视频)
今天大家已经被winhec刷屏了,本来不想写这篇了,但看了所有的文章,大家关注的都是windows 10的那些新功能,小米win10刷机,联想千元手机,小娜啥的.对于keynote上第二部分 Don ...
- 全面理解JavaScript中的闭包的含义及用法
1.什么是闭包 闭包:闭包就是能够读取其他函数内部变量的函数;闭包简单理解成“定义在一个函数内部的函数”. 闭包的形式:即内部函数能够使用它所在级别的外部函数的参数,属性或者内部函数等,并且能在包含它 ...
- Asp.net MVC验证哪些事(2)-- 验证规则总结以及使用
上篇文章Asp.net MVC验证那些事(1)-- 介绍和验证规则使用中,介绍了Asp.net MVC中的验证功能以及如何使用.这里将对MVC中内置的验证规则进行总结. 一,查找所有验证规则 上篇文章 ...
- JavaScript(七)——视频插入
代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3. ...
- 安装 gcc-c++ 时报错和原有 gcc 版本冲突
Centos 6.7 安装 gcc-c++时报下面的错误: Resolving Dependencies --> Running transaction check ---> :-.el6 ...
- 烂泥:Linux源码包制作RPM包之Apache
本文由秀依林枫提供友情赞助,首发于烂泥行天下 公司服务器比较多,需要把apache源码包制作成rpm包,然后放到公司内网yum源上进行下载安装.apache的rpm包安装方式比源码安装方式比较快,这能 ...
- 使用 python 发送邮件
1.使用python 写发邮箱代码: def sendmail (): import smtplib from email.mime.text import MIMEText from email.u ...