二叉树遍历分为三种:

  1. 先序遍历:先访问根结点,其次左节点,最后右节点

  2. 中序遍历:先访问左结点,其次跟节点,最后右节点

  3. 后序遍历:先访问左结点,其次右节点,最后根节点

三种遍历的递归算法实现形式类似,仅仅是访问顺序不同,非常简洁。如下:

//节点定义
typedef struct node {int val;struct node *left;struct node *right;
}*pnode, node;
//后序遍历递归算法
void postOrderRecursive(pnode root)
{if (root){//访问左子树postOrderRecursive (root->left);//访问右子树postOrderRecursive (root->right);//访问根结点printf("%d ", root->val);       }return ;
}//中序遍历递归算法
void inOrderRecursive(pnode root)
{if (root){//访问左子树inOrderRecursive (root->left);//访问根结点printf("%d ", root->val);//访问右子树inOrderRecursive (root->right);       }return ;
}//先序遍历递归算法
void preOrderRecursive(pnode root)
{if (root){printf("%d ", root->val);//访问左子树preOrderRecursive (root->left);//访问右子树preOrderRecursive (root->right);        }return ;
}

递归算法属于必知必会的基础,面试如果问到此类问题,一般都会让给出非递归实现。话说,递归算法一般都可以转换成循环和栈的非递归实现。

对于先序遍历来说,先将根结点入栈,进入循环,取栈顶,先将节点右孩子和左孩子依次进栈,访问该节点,按照此节奏,循环处理,直到栈空。即,每次取出栈顶元素,将其右左孩子节点依次进栈,访问即可。

//先序遍历非递归
void preOrderNonRec(pnode root)
{pnode stack[1000], curr, prev;int top, end;if (root == NULL)return ;top = end = 0;//根结点入栈stack[top++] = root;while (top > 0){//取栈顶curr = stack[--top];//右子树入栈if (curr->right)stack[top++] = curr->right;//左子树入栈    if (curr->left)stack[top++] = curr->left;//访问节点    printf ("%d ", curr->val); }printf("\n");return ;
}

对于中序遍历的非递归算法,依然是栈加循环的方式,处理上和上一步略微有点区别。

先将根结点入栈,当前节点指向左孩子,只要当前节点的左孩子存在,则继续循环处理,即父节点进栈,节点指向左孩子,直到节点为空,这时,从栈中取出栈顶,对于栈中取出的元素,总是先访问,然后指向右孩子,继续第一步处理,即父节点进栈,节点指向左孩子。这里需要注意的有两点:1. 从栈中取出来的元素访问后无需再进栈。2. 对于栈中取出的元素,总是先访问,然后指向右孩子。

//中序遍历,非递归
void inorderNonRec(pnode root)
{pnode stack[1000], curr;int top, end;if (root == NULL)return ;top = end = 0;//根结点进栈stack[top++] = root;//当前节点指向左孩子curr = root->left;while (curr || top > 0){//节点存在,则父节点进栈,指向左孩子if (curr){if (curr->left){stack[top++] = curr;curr = curr->left;continue;}}else{curr = stack[--top];}//取栈顶,访问后,指向右孩子printf("%d ", curr->val);curr = curr->right;}printf("\n");return ;
}

后序遍历的非递归实现依然是循环加栈处理。和中序遍历一样,不过处理上略微有点不同。相当之处仍然是父节点先进栈,指向左孩子。不同的地方在于,从栈中取出元素时,此时不访问,而是如果存在右孩子,则父节点继续进栈,节点指向其右孩子。如果右孩子不存在,则访问该节点,同时记录当前访问的节点。继续出栈,同上步,如果存在右孩子,父节点继续进栈,节点指向其右孩子,此时,为防止死循环,需要将右孩子和之前访问的节点比较,如果相同,则无需进栈,此时直接访问即可。不理解的同学请画一颗二叉树辅助思考。

//后序遍历,非递归
void postOrderNonRec(pnode root)
{pnode stack[1000], curr, prev;int top, end;if (root == NULL)return ;top = end = 0;//根结点入栈stack[top++] = root;//指向左孩子curr = root->left;while (curr || top > 0){//只要存在孩子节点,则父节点进栈,指向其孩子节点。if (curr){if (curr->left || curr->right){stack[top++] = curr;if (curr->left)curr = curr->left;elsecurr = curr->right;  continue;}}else{//取栈顶,如果存在右孩子且和上一个访问节点不一样,则父节点//继续进栈,指向右孩子。curr = stack[--top];if (curr->right && curr->right != prev){stack[top++] = curr;             curr = curr->right;continue;}}//访问节点同时保存访问的位置。printf("%d ", curr->val);prev = curr;curr = NULL;}printf("\n");return ;
}

=============================================================================================

Linux应用程序、内核、驱动、后台开发交流讨论群(745510310),感兴趣的同学可以加群讨论、交流、资料查找等,前进的道路上,你不是一个人奥^_^。

二叉树遍历算法的六种c语言实现 递归与非递归相关推荐

  1. 【C语言】二叉树中序遍历(递归和非递归)算法

    二叉树中序遍历的实现思想是: 访问当前节点的左子树: 访问根节点: 访问当前节点的右子树: 图 1 二叉树 以图  1 为例,采用中序遍历的思想遍历该二叉树的过程为: 访问该二叉树的根节点,找到 1: ...

  2. 二叉树遍历算法详解(递归法+非递归法)

    二叉树遍历算法详解 在上一篇C语言实现二叉树中有提到对于二叉树的遍历,包括前序,中序和后续遍历,以及层次遍历 大家已经熟悉了二叉树的前中后序遍历过程,大部分都采用了递归的思想来实现 在leetcode ...

  3. C#二叉树遍历算法实现浅析

    C#算法实现了二叉树的定义,怎么构造一颗已知的二叉树,用几种常规的算法(先序,中序,后序,层次)进行C#二叉树遍历.希望能给有需要人带来帮助,也希望能得到大家的指点.有关C#数据结构的书在书店里找到, ...

  4. 九十五、二叉树的递归和非递归的遍历算法模板

    @Author:Runsen 刷Leetcode,需要知道一定的算法模板,本次先总结下二叉树的递归和非递归的遍历算法模板. 二叉树的四种遍历方式,前中后加上层序遍历.对于二叉树的前中后层序遍历,每种遍 ...

  5. 二叉树创建及遍历算法(递归及非递归)(转)

    //二叉树处理头文件 //包括二叉树的结构定义,二叉树的创建,遍历算法(递归及非递归), /* 作者:成晓旭 时间:2001年10月7日(18:49:38-20:00:00) 内容:完成二叉树创建,二 ...

  6. 基于计数栈的非递归二叉树遍历算法

    转载请保留完整信息! 作者:中山大学 赵耀 10389332 创作时间:2013.11.25 发表时间:2013.12.11 背景 遍历算法一般可按深度优先或广度优先进行.对于二叉树,深度优先遍历可分 ...

  7. 【树】二叉树遍历算法(深度优先、广度优先遍历,前序、中序、后序、层次)及Java实现...

    [树]二叉树遍历算法(深度优先.广度优先遍历,前序.中序.后序.层次)及Java实现 目录 一.前序遍历 二.中序遍历 三.后序遍历 四.层次遍历 遍历的作用 二叉树是一种非常重要的数据结构,很多其它 ...

  8. C语言实现二叉树前序中序后序递归与非递归遍历、层次遍历、二叉树带权路径长度

    用C语言实现了二叉树的初始化,循环队列与顺序栈的建立. 利用递归与非递归方式实现前序遍历.中序遍历.后序遍历. 利用队列实现了层次遍历. 求得了二叉树带权路径长度 #include<stdio. ...

  9. 二叉树遍历算法的应用——计算二叉树的深度、计算二叉树的节点总数、计算二叉树的叶子节点数(均采用递归的思想)

    //二叉树遍历算法的应用 //1.计算二叉树的深度 int Depth(BitTree T){if(T==NULL)return 0;//如果是空树,返回0else{m=Depth(T->lch ...

最新文章

  1. window.print()方法,如何获取打印弹框显示状态
  2. noip2016考前模板
  3. ICDM 2020 TOP3方案
  4. 部署承载于 Internet 信息服务中的 WCF 服务
  5. 规则引擎:大厂营销系统资格设计全解
  6. 设计模式学习笔记一——开篇
  7. 电脑开机3秒就重启循环_电脑修好后客户不愿支付上门费,行,那电脑开机60秒自动关机吧!...
  8. java代码god类_java – 如何编写Controller而不将其作为God对象?
  9. 董事长亲自“翻墙偷拍”后,身价暴涨3000万
  10. 理解asp.net中DropDownList编辑数据源,绑定数据库数据。
  11. maven自动部署到tomcat的问题
  12. 感知机算法—推导收敛次数的上界
  13. 备战数学建模14-熵权法确定指标权重系数
  14. HTTP协议和APACHE
  15. JavaScript学习之面向对象编程-04
  16. 带轮轮毂长度l和带轮宽b表_V带轮宽度怎么计算?知道是A型带,带数为6,轮缘宽、轮彀孔径与长度怎么计算?顺求公式...
  17. OpenLayers 3 之 Overlay(覆盖物)详解
  18. 天啦,从Mongo到ClickHouse我到底经历了什么?
  19. 操作系统考研复试、工作面试常见问题及答案
  20. 网络推广100法,果然很强悍。

热门文章

  1. Python中单下划线开头的特性
  2. JS解析XML文件和XML字符串
  3. 计算硼原子基态能级B---动能和势能
  4. java中的alert是什么意思_javascript 中如何使用alert?
  5. 【数理知识】《积分变换与场论》王振老师-第3章-矢量与矢量空间
  6. 【数理知识】《数值分析》李庆扬老师-第7章-非线性方程与方程组的数值解法
  7. Ardino基础教程 18_驱动74HC595
  8. 一起学nRF51xx 2 - clock
  9. 彻底弄懂ICG的基本概念
  10. 使用Android内部的DownloadProvider下载文件,并获取cache权限 .