二叉树遍历遐想
2016-02-28 15:14
288 查看
二叉树遍历,按遍历顺序分:前序,中序,后序。
二叉树遍历,按代码实现分:递归和非递归。
看到递归和非递归代码的实现,不禁好奇,为什么同样遍历顺序,为什么代码的复杂度差这么远?
以前虽然好奇,但没有细想。今天琢磨琢磨下。抛砖引玉,有什么不对地方请指出。
结论:
其实二叉树遍历必须依靠栈或者队列数据结构。二叉树有2个分支,而在一个函数中不依靠栈或者队列,只能一个方向进行遍历。遍历的递归和非递归其实本质都是一样的,利用栈实现路径记录。只是递归实现中,我们使用的是隐形的栈:函数调用栈,巧妙地把任务交个程序运行机制来完成,但这样利用函数调用栈,对程序性能和内存都有损耗。非递归实现中,需要我们自己来实现栈。因此两种方法的优劣一目了然了。
非递归实现:实现相对复杂,节省内存,性能好,
递归实现 :实现简单,比较耗内存,性能没有非递归好。
非递归代码参考:松阳的blog:二叉树非递归代码参考
可以从图中看出:
1.非递归和递归方法的出栈入栈顺序是可以不一样的。
2.递归方法的出栈入栈顺序一样,数据访问位置不一样,造成前中后序访问。
3.非递归前序和中序的入栈出栈顺序是一样的,只是数据访问位置不一样。
4.后序遍历的非递归和递归使用的出栈入栈顺序是相同的。若修改在后序遍历非递归方法中访问data的位置,是否会变成和递归的效果一样呢(在入栈是访问、出栈时访问、左子树遍历完成)?
前序
递归调用
void pretravel(BtreeNode* root ){
if(root !=null)
dosomething(root->data);//在入栈时访问当前节点
pretravel(root->left);//调用这个函数说明,当前root入栈。
pretravel(root->right);
}
中序
递归调用
void pretravel(BtreeNode* root ){
if(root !=null)
pretravel(root->left);//调用这个函数说明,当前root入栈。
dosomething(root->data);//在左子树遍历完成后访问当前节点
pretravel(root->right);
}
后序
递归调用
void pretravel(BtreeNode* root ){
if(root !=null)
pretravel(root->left);//调用这个函数说明,当前root入栈。
pretravel(root->right);
dosomething(root->data);//左右子树访问完成,当前节点出栈时,访问当前节点。
}
今天先到这里。
二叉树遍历,按代码实现分:递归和非递归。
看到递归和非递归代码的实现,不禁好奇,为什么同样遍历顺序,为什么代码的复杂度差这么远?
以前虽然好奇,但没有细想。今天琢磨琢磨下。抛砖引玉,有什么不对地方请指出。
结论:
其实二叉树遍历必须依靠栈或者队列数据结构。二叉树有2个分支,而在一个函数中不依靠栈或者队列,只能一个方向进行遍历。遍历的递归和非递归其实本质都是一样的,利用栈实现路径记录。只是递归实现中,我们使用的是隐形的栈:函数调用栈,巧妙地把任务交个程序运行机制来完成,但这样利用函数调用栈,对程序性能和内存都有损耗。非递归实现中,需要我们自己来实现栈。因此两种方法的优劣一目了然了。
非递归实现:实现相对复杂,节省内存,性能好,
递归实现 :实现简单,比较耗内存,性能没有非递归好。
非递归代码参考:松阳的blog:二叉树非递归代码参考
可以从图中看出:
1.非递归和递归方法的出栈入栈顺序是可以不一样的。
2.递归方法的出栈入栈顺序一样,数据访问位置不一样,造成前中后序访问。
3.非递归前序和中序的入栈出栈顺序是一样的,只是数据访问位置不一样。
4.后序遍历的非递归和递归使用的出栈入栈顺序是相同的。若修改在后序遍历非递归方法中访问data的位置,是否会变成和递归的效果一样呢(在入栈是访问、出栈时访问、左子树遍历完成)?
前序
递归调用
void pretravel(BtreeNode* root ){
if(root !=null)
dosomething(root->data);//在入栈时访问当前节点
pretravel(root->left);//调用这个函数说明,当前root入栈。
pretravel(root->right);
}
中序
递归调用
void pretravel(BtreeNode* root ){
if(root !=null)
pretravel(root->left);//调用这个函数说明,当前root入栈。
dosomething(root->data);//在左子树遍历完成后访问当前节点
pretravel(root->right);
}
后序
递归调用
void pretravel(BtreeNode* root ){
if(root !=null)
pretravel(root->left);//调用这个函数说明,当前root入栈。
pretravel(root->right);
dosomething(root->data);//左右子树访问完成,当前节点出栈时,访问当前节点。
}
今天先到这里。
相关文章推荐
- 最小表示法的学习
- JS闭包小结
- uva 11134 传说中的车 从简单情形入手
- 一个高效的UI才是一个拉风的UI(二)
- 【codevs】4633 树链剖分入门
- 关于安装MySQLdb出现fatal error: my_config.h: No such file or directory
- 个人学习-java-抽象类(abstract class)
- sass @extend
- andriod 剪贴板操作
- eclipse开发c++时cout和endl报错
- 基类和派生类:谈继承
- 聊天云通讯
- c#---通过xml读取数据库
- 一个高效的UI才是一个拉风的UI(一)
- 求当前月的第一天和最后一天
- Jsonp 复习笔记
- record about Network socket API
- 新生项目总结之---组织管理与文档的书写
- sass @media
- ios-同步下载与异步下载