二叉树的遍历(递归,迭代,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)个空指针域.利用二叉链表中的空指针域,存放指向结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索 ...
随机推荐
- Android 学习资料收集
收集整理这份资料灵感来自于 trip_to_iOS, 征得同意引用了该资料的开头描述 收集整理这份资料主要帮助初学者学习 Android 开发, 希望能快速帮助到他们快速入门, 找到适合自己学习资料, ...
- post请求报文
POST /02_WEB_HTTP/index.html HTTP/1.1 Accept: application/x-ms-application, image/jpeg, application/ ...
- C# MVC模式 404 500页面设置方法
<customErrors mode="On" defaultRedirect="Controllers/Action"> <error st ...
- ExtJs4.1中给列表的单元格设置颜色
如: 代码: { xtype: 'gridcolumn', ...
- CentOS vsftp安装与配置
详细配置说明:. http://www.cnblogs.com/app-lin/p/5189762.html 1.安装vsftpd yum install vsftpd 2.启动/重启/关闭vsftp ...
- HTML基础(一)——一般标签、常用标签和表格
第一部分 HTML <html> --开始标签 <head> 网页上的控制信息 <title>页面标题</title> </head> ...
- [Linux 性能检测工具]VMSTAT
VMSTAT NAME: Vmstat: 报告虚拟内存统计 语法 : vmstat [-a] [-n] [-t] [-S unit] [delay [ count]] ...
- MongoDB 常用故障排查工具
1.profile profiling levels: 0,关闭profile:1,只抓取slow查询:2,抓取所有数据. 启动profile并且设置Profile级别: 可以通过mongo shel ...
- Druid 介绍及配置
1. Druid是什么? Druid是Java语言中最好的数据库连接池.Druid能够提供强大的监控和扩展功能. 2. 在哪里下载druid 正式版本下载:maven中央仓库: http://cent ...
- 身份证校验(java)
判断是第几代身份证(第一代15位, 第二代18位) if (cardId.length() == 15 || cardId.length() == 18) { if (!this.cardCodeVe ...