您的位置:首页 > 其它

二叉树遍历遐想

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);//左右子树访问完成,当前节点出栈时,访问当前节点。

}


今天先到这里。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: