博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
二叉树先序遍历算法实现
阅读量:6480 次
发布时间:2019-06-23

本文共 2489 字,大约阅读时间需要 8 分钟。

循环遍历方法--先序遍历

对于数据结构这方面来说,重点就是二叉树的遍历等操作,所有的问题基本都是集中在这里,先说一个二叉树的循环遍历的方法:

vector
preOrderTraversal(TreeNode *head){ vector
result; const TreeNode *p; stack
s; p = head; if(p != NULL) s.push(p); while(!s.empty()) { p = s.top(); s.pop(); result.push_back(p->val); if(p->right != NULL) s.push(p->left); if(p->left != NULL) s.push(p->left); } return result;}

  注意vector和stack的使用,遍历的结果放到了一个vector中,并且返回给调用函数。

同时还要注意先序遍历中根、左、右的顺序,压栈的时候要先压右孩子,然后再压左孩子,这样才能先访问左孩子。

Morris遍历方法

如果不用栈作为辅助的工具,不用递归调用的话,那就得记住这个根节点,当遍历完这个根节点的左子树的时候,能通过这个根节点找到它的右子树,然后继续遍历这个右子树。所以记下这个根节点是关键。

之前用的方法都是用栈保存根节点,Morris用左子树的最后一个结点(最右边的叶子结点)的右指针域来保存根节点。

当左子树遍历完成之后,最后一个遍历的结点的右指针域就指向了原根节点。

为了防止整个遍历过程陷入死循环,当遍历完根节点的左子树。第二次回到根节点的时候,不应该继续遍历这个根节点的左子树了,而是能够转向根节点的右子树,所以用左子树的最后一个右叶结点的右指针域是否已经指向了这个根节点作为标志,表明根节点的左子树是否已经遍历过。

1.如果当前结点有左子树	找到左子树的最右叶节点	使最右叶节点的右指针域指向该根节点	p = p->left转向左子树2.如果当前结点没有左子树	访问这个结点	p = p->right转向右子树

  这个算法存在一个问题,如下面的图所示:

当前结点指向B结点的时候,找到B结点的左子树的最右叶节点,也就是C结点,使C得右指针域指向B。然后当前结点指向C,C没有左子树,所以访问C,当前结点转向C的右指针域,也就是转向了B结点,但是这时候B结点仍然是有左子树的,当在B的左子树中找最右叶节点的时候,陷入死循环,因为这里已经构成了一个环,所以要能侦测B的左子树的最右叶节点的右指针域是否已经指向了B,是的话证明,B的左子树已经访问过了,下面就可以访问B,然后再访问B的右子树了。

1.如果当前结点有左子树    找到左子树的最右叶节点         如果最右叶结点的右指针域指向该结点(第二次访问)        把这个最右叶结点的右指针域置为NULL        p = p->right转向右子树    否则(第一次访问)        访问该结点		使最右叶节点的右指针域指向该根节点        p = p->left转向左子树2.如果当前结点没有左子树    访问这个结点    p = p->right转向右子树

  

  Morris算法的代码实现:

vector
preOrder(TreeNode *root){ TreeNode *pCur = root; TreeNode *pTemp = NULL; vector
result; while(pCur != NULL) { if(pCur->left != NULL) { pTemp = pCur->left; while(pTemp->right != NULL && pTemp->right != pCur) { pTemp = pTemp->right; }//while //判断while循环结束的原因 if(pTemp->right == NULL)//第一次访问根节点pCur的左子树 { //访问当前结点 result.push_back(pCur->val); //当前结点的左子树的最右结点的右指针域指向当前结点 pTemp->right = pCur; //当前结点转向其左子树 pCur = pCur->left; } else//第二次访问根节点pCur的左子树pTemp->right == pCur { //恢复原来的树结构 pTemp->right = NULL; //然后转向右子树 pCur = pCur->right; } }//if else { //对于没有左子树的根节点,访问该当前结点,并转向其右子树 result.push_back(pCur->val); pCur = pCur->right; }//else }//while return result;}

  

转载于:https://www.cnblogs.com/stemon/p/4657382.html

你可能感兴趣的文章
生活杂事--度过十一中秋
查看>>
Pyrex也许是一个好东西
查看>>
WINFORM WPF字体颜色相互转换
查看>>
能力不是仅靠原始积累(三)
查看>>
实战:使用终端服务网关访问终端服务
查看>>
彻底学会使用epoll(一)——ET模式实现分析
查看>>
脱离标准文档流(2)---定位
查看>>
IO流之字符流
查看>>
集合异常之List接口
查看>>
Softmax回归
查看>>
紫书 习题11-11 UVa 1644 (并查集)
查看>>
App工程结构搭建:几种常见Android代码架构分析
查看>>
使用openssl进行证书格式转换
查看>>
ZOJ 3777 Problem Arrangement
查看>>
Callable和Future
查看>>
少用数字来作为参数标识含义
查看>>
ScrollView中嵌套ListView
查看>>
Algs4-2.3.1如何切分数组
查看>>
观察者模式
查看>>
在properties.xml中定义变量,在application.xml中取值问题
查看>>