用递归非递归两种方法遍历二叉树
- 格式:doc
- 大小:287.54 KB
- 文档页数:14
数据结构⽤⾮递归算法求⼆叉树⾼度算法思想: 采⽤层次遍历的算法,设置变量level记录当前节点所在层数,设置变量last指向当前层的最右结点,每层遍历出队时与last指针⽐较,若两者相等,则层数加⼀,并让last指向下⼀层的最右结点即rear所在位置,直到变量完成。
level的值即为⼆叉树的⾼度。
代码如下:1int Btdepth(BiTree T)2 {3if(T==NULL) //树空⾼度为04return0;5int front=rear=-1;6int last=level=0; //last指向当前层的最右结点7 BiTree Q[MAXSIZE]; //设置队列Q,元素是⼆叉树结点指针且容量⾜够8 Q[++rear]=T; //将根节点⼊队9 BiTree p=T;10while(!IsEmpty(Q)) //11 {12 p=Q[++front]; //队列元素出队,即正在访问的结点13if(p->lchild)14 Q[++rear]=p->lchild; //左孩⼦⼊队15if(p->rchild)16 Q[++rear]=p->rchild; //右孩⼦⼊队17if(front==last) //访问到该层的最后⼀个结点18 {19 level++; //⾼度加⼀20 last=rear; //更新last指向下⼀层最右⼀个结点21 }2223 }24return level;25 }扩展:求某⼀层的结点个数,每层的结点个数、树的最⼤宽度,都采⽤与此题类似的思想。
当然,此题可采⽤递归算法,其实现如下代码如下:1int Btdepth(BiTree T)2 {3if(T==NULL) //空树⾼度为04return0;5 ldep=Btdepth(T->lchild); //递归遍历左⼦树6 rdep=Btdepth(T->rchild); //递归遍历右⼦树7if(ldep>rdep) //树的⾼度为⼦树的最⼤⾼度加根节点8return ldep+1;9else10return rdep+1;11 }。
golang 中序遍历递归非递归中序遍历是二叉树遍历的一种方式,以左子树、根节点、右子树的顺序访问节点。
在Golang中,我们可以使用递归和非递归两种方式实现中序遍历。
一、递归实现中序遍历递归实现中序遍历是最简单直观的方式。
我们可以定义一个递归函数,用于按中序遍历访问树的节点。
```gopackage mainimport "fmt"type TreeNode struct {Val intLeft *TreeNodeRight *TreeNode}func inorderTraversal(root *TreeNode) {if root != nil {inorderTraversal(root.Left)fmt.Printf("%d ", root.Val)inorderTraversal(root.Right)}}func main() {// 构造一棵二叉树root := &TreeNode{Val: 1}root.Left = &TreeNode{Val: 2}root.Right = &TreeNode{Val: 3}root.Left.Left = &TreeNode{Val: 4}root.Left.Right = &TreeNode{Val: 5}fmt.Println("中序遍历结果:")inorderTraversal(root)}```以上代码中,我们先构造了一棵二叉树,然后调用`inorderTraversal`函数进行中序遍历。
递归函数首先检查根节点是否为空,如果不为空,则按照左子树、根节点、右子树的顺序递归调用自身。
二、非递归实现中序遍历非递归实现中序遍历使用栈来模拟递归的过程。
具体实现过程如下:```gopackage mainimport "fmt"type TreeNode struct {Val intLeft *TreeNodeRight *TreeNode}func inorderTraversal(root *TreeNode) { stack := []*TreeNode{}cur := rootfor len(stack) > 0 || cur != nil {for cur != nil {stack = append(stack, cur)cur = cur.Left}cur = stack[len(stack)-1]stack = stack[:len(stack)-1]fmt.Printf("%d ", cur.Val)cur = cur.Right}}func main() {// 构造一棵二叉树root := &TreeNode{Val: 1}root.Left = &TreeNode{Val: 2}root.Right = &TreeNode{Val: 3}root.Left.Left = &TreeNode{Val: 4}root.Left.Right = &TreeNode{Val: 5}fmt.Println("中序遍历结果:")inorderTraversal(root)}```以上代码中,我们定义了一个栈和一个指针`cur`,其中栈用于存储遍历过程中的节点。
二叉树后序遍历的非递归算法
二叉树后序遍历是指按照左子树、右子树、根节点的顺序遍历二叉树的过程。
与前序遍历和中序遍历不同,后序遍历需要考虑根节点的位置,因此需要使用栈来存储节点信息。
非递归算法一般使用栈来实现,因为后序遍历的过程中需要先遍历左子树和右子树,最后才遍历根节点,所以存储节点信息的栈需要进行一些特殊处理。
下面是二叉树后序遍历的非递归算法:
1. 创建一个空栈,并将根节点入栈。
2. 创建一个辅助变量pre表示上一个被遍历的节点。
3. 当栈不为空时,取出栈顶元素top,判断它是否为叶子节点或者它的左右子节点都被遍历过了(被遍历过的节点可以通过辅助变量pre来判断)。
4. 如果top为叶子节点或者它的左右子节点都被遍历过了,则将top出栈,并将它的值输出。
5. 如果不满足条件3,判断top的右子节点是否为pre,如果是,则说明右子树已经遍历完了,此时可以直接输出top的值,并将top出栈;如果不是,则将top的右子节点入栈。
6. 将top的左子节点入栈。
7. 将上一个被遍历的节点pre更新为top。
根据这个算法,我们可以分别对左子树和右子树进行遍历,并保证根节点最后被遍历到,从而实现二叉树的后序遍历。
这个算法的时间复杂度为O(n),空间复杂度为O(n)。
总的来说,二叉树的后序遍历是一种比较复杂的遍历方式,需要使用栈保存节点信息,并且需要特殊处理根节点的位置。
使用非递归算法实现后序遍历可以优化空间复杂度和避免栈溢出的问题。
数据结构求二叉树的深度二叉树深度是指从根节点到最远叶子节点的最长路径上的节点数量。
求二叉树的深度是一个常见的问题,通常可以用递归或者非递归的方式来解决。
一、递归方法:递归是一种自上而下的解决问题的方式,在求二叉树深度时,可以使用递归来解决。
递归的思路是,对于一个根节点,它的深度等于其左子树和右子树中较大的深度加1下面是递归方法的实现,以Python语言为例:```def get_depth(root):if root is None:return 0left_depth = get_depth(root.left)right_depth = get_depth(root.right)return max(left_depth, right_depth) + 1```该递归函数的基本情况是,如果根节点为空,则深度为0;否则,递归计算左子树和右子树的深度,并取较大值,最后加1即为整个二叉树的深度。
二、非递归方法:非递归方法是一种自下而上的解决问题的方式,在求二叉树深度时,可以使用非递归的方式来解决。
非递归的思路是,使用层次遍历的方式遍历二叉树的每一层,每遍历一层,深度加1,直到遍历完所有节点。
下面是非递归方法的实现,以Python语言为例:```def get_depth(root):if root is None:return 0depth = 0queue = [root]while queue:depth += 1level_size = len(queue)for _ in range(level_size):node = queue.pop(0)if node.left:queue.append(node.left)if node.right:queue.append(node.right)return depth```该非递归函数的基本思路是,首先判断根节点是否为空,如果为空则深度为0;否则,初始化深度为0和一个队列,将根节点入队,然后进入循环,每一次循环代表一层,首先将循环变量level_size设置为队列的长度,然后将队头元素出队,并将其左右子节点入队,直到队列为空。
判断两颗⼆叉树是否相似的两种⽅法名称:判断两个⼆叉树是否相似说明:此处的两个⽅法⼀个是⾮递归,⼀个是递归算法。
其实两个算法的本质思路是⼀样的就是,判断位置相同的两个结点是否同时为空或同时不为空。
只是具体的实现不⼀样。
对于层次遍历法:此处不⼩⼼⽤错了,本应该⽤队列来当作排列下⼀层元素的。
歪打正着,此处⽤栈也可以,只是判断的结点顺序不⼀样。
队列的话,是从每⼀层的左端到右端。
栈的话,是从右端到左端。
在此处都没影响。
我去,有发现⼀点,要从右到左访问⼀层的元素的话,应该⽤栈。
对于递归,看起来⽐⾮递归要简单不少。
基本的思路很简单,要注意的是,在程序需要从⼦树接收返回是否相似的信息。
这样的话,有⼀个问题,就是必须等树完全判断完才可以最终返回。
不想上⾯的,过程中发现不⼀样就可以⽴即返回了。
//层次遍历法判断两棵树是否相似bool IsSemblable1(BiTree T1,BiTree T2){stack<BiTNode* > _sta1,_sta2; //⽤来存放下⼀层元素的容器,此处栈和队列都⾏BiTNode *p1 = T1,*p2 = T2; //p1⽤来跟踪T1,p2⽤来跟踪T2while((_sta1.empty() == false || p1 != NULL) &&(_sta2.empty() == false || p2 != NULL)){if(p1 != NULL && p2 != NULL ) //如果p1和p2都不为空时{if(p1->lchild != NULL && p2->lchild != NULL) //如果p1和p2的左⼦树都不为空时{_sta1.push(p1->lchild);_sta2.push(p2->lchild);}else if( p1->lchild != NULL || p2->lchild != NULL) //如果p1的左⼦树为空,但是p2的左⼦树不为空,或者相反return false;if(p1->rchild != NULL && p2->rchild != NULL) //如果p1和p2的右⼦树都不为空时{_sta1.push(p1->rchild);_sta2.push(p2->rchild);}else if(p1->rchild != NULL || p2->rchild != NULL) //如果p1的右⼦树为空,但是p2的右⼦树不为空,或者相反return false;//访问完两棵树的当前结点后,置空让下⼀次循环弹出栈中元素(此处其实直接弹出元素也⾏)p1 = NULL;p2 = NULL;}else if(p1 != NULL || p2 != NULL) //当前节点有⼀个为空return false;else{//弹出两个树的栈顶元素p1 = _sta1.top();p2 = _sta2.top();_sta1.pop();_sta2.pop();}}return true;}//递归判断两棵树是否相似bool IsSemblable2(BiTree T1,BiTree T2){bool leftS = false,rightS = false; //⽤来接受⼦树返回的信息if(T1 == NULL && T2 == NULL) //两个结点都为空return true;else if(T1 == NULL || T2 == NULL) //有⼀个结点不为空return false;else{int leftS = IsSemblable2(T1->lchild,T2->lchild); //递归左⼦树int rightS = IsSemblable2(T1->rchild,T2->rchild); //递归右⼦树return leftS && rightS ; //返回两个⼦树的信息}}总结以上就是这篇⽂章的全部内容了,希望本⽂的内容对⼤家的学习或者⼯作具有⼀定的参考学习价值,谢谢⼤家对的⽀持。
二叉树的遍历实验报告一、实验目的1.了解二叉树的基本概念和性质;2.理解二叉树的遍历方式以及它们的实现方法;3.学会通过递归和非递归算法实现二叉树的遍历。
二、实验内容1.二叉树的定义在计算机科学中,二叉树是一种重要的数据结构,由节点及它们的左右儿子组成。
没有任何子节点的节点称为叶子节点,有一个子节点的节点称为一度点,有两个子节点的节点称为二度点。
二叉树的性质:1.每个节点最多有两个子节点;2.左右子节点的顺序不能颠倒,左边是父节点的左子节点,右边是父节点的右子节点;3.二叉树可以为空,也可以只有一个根节点;4.二叉树的高度是从根节点到最深叶子节点的层数;5.二叉树的深度是从最深叶子节点到根节点的层数;6.一个深度为d的二叉树最多有2^(d+1) -1个节点,其中d>=1;7.在二叉树的第i层上最多有2^(i-1)个节点,其中i>=1。
2.二叉树的遍历方式二叉树的遍历是指从根节点出发,按照一定的顺序遍历二叉树中的每个节点。
常用的二叉树遍历方式有三种:前序遍历、中序遍历和后序遍历。
前序遍历:先遍历根节点,再遍历左子树,最后遍历右子树;中序遍历:先遍历左子树,再遍历根节点,最后遍历右子树;后序遍历:先遍历左子树,再遍历右子树,最后遍历根节点。
递归算法:利用函数调用,递归实现二叉树的遍历;非递归算法:利用栈或队列,对二叉树进行遍历。
三、实验步骤1.创建二叉树数据结构并插入节点;2.实现二叉树的前序遍历、中序遍历、后序遍历递归算法;3.实现二叉树的前序遍历、中序遍历、后序遍历非递归算法;4.测试算法功能。
四、实验结果1.创建二叉树数据结构并插入节点为了测试三种遍历方式的算法实现,我们需要创建一个二叉树并插入节点,代码如下:```c++//定义二叉树节点struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}};递归算法是实现二叉树遍历的最简单方法,代码如下:```c++//前序遍历非递归算法vector<int> preorderTraversal(TreeNode* root) {stack<TreeNode*> s;vector<int> res;if (!root) return res;s.push(root);while (!s.empty()) {TreeNode* tmp = s.top();s.pop();res.push_back(tmp->val);if (tmp->right) s.push(tmp->right);if (tmp->left) s.push(tmp->left);}return res;}4.测试算法功能return 0;}```测试结果如下:preorderTraversal: 4 2 1 3 6 5 7inorderTraversal: 1 2 3 4 5 6 7postorderTraversal: 1 3 2 5 7 6 4preorderTraversalNonRecursive: 4 2 1 3 6 5 7inorderTraversalNonRecursive: 1 2 3 4 5 6 7postorderTraversalNonRecursive: 1 3 2 5 7 6 4本次实验通过实现二叉树的递归和非递归遍历算法,加深了对二叉树的理解,并熟悉了遍历算法的实现方法。
二叉树的遍历教案教学设计教案教学设计:二叉树的遍历一、教学目标:1. 了解二叉树的遍历方式:前序遍历、中序遍历和后序遍历。
2. 能够使用递归和非递归两种方法实现二叉树的遍历。
3. 能够分析和比较不同遍历方式的时间复杂度和空间复杂度。
二、教学内容:1. 二叉树的遍历概念及分类。
2. 递归遍历算法的原理及实现。
3. 非递归遍历算法的原理及实现。
4. 比较不同遍历方式的时间复杂度和空间复杂度。
三、教学重点:1. 能够理解二叉树的遍历分类及其特点。
2. 能够使用递归和非递归两种方法实现二叉树的遍历。
四、教学难点:1. 非递归遍历算法的实现。
2. 比较不同遍历方式的时间复杂度和空间复杂度。
五、教学过程:1. 导入新知识,激发学生兴趣(5分钟)教师通过展示一棵二叉树的图片引入二叉树的遍历概念,并让学生猜测遍历的意义。
2. 介绍二叉树的遍历分类及特点(10分钟)教师介绍二叉树的遍历分类:前序遍历(根-左-右)、中序遍历(左-根-右)和后序遍历(左-右-根),并讲解每种遍历方式的特点。
3. 介绍递归遍历算法的原理及实现(15分钟)教师通过演示前序遍历的递归算法实现,介绍递归遍历的原理和递归函数的编写,让学生理解递归遍历的思路。
4. 演示递归遍历算法的应用(15分钟)教师在白板上画一棵二叉树,演示如何使用递归算法实现不同的遍历方式,并让学生跟随演示进行练习。
5. 介绍非递归遍历算法的原理及实现(15分钟)教师介绍非递归遍历算法的思路,包括使用栈数据结构进行遍历的原理及实现。
6. 演示非递归遍历算法的应用(15分钟)教师在白板上画一棵二叉树,演示如何使用非递归算法实现不同的遍历方式,并让学生跟随演示进行练习。
7. 比较不同遍历方式的时间复杂度和空间复杂度(10分钟)教师比较不同遍历方式的时间复杂度和空间复杂度,让学生了解不同的遍历方式在不同场景下的优劣。
8. 小结与作业布置(5分钟)教师对本节课进行小结,并布置作业:编写一个程序,实现二叉树的遍历,并分析所用遍历方式的时间复杂度和空间复杂度。
二叉树经典例题的题解本文将为大家详细介绍几个经典的二叉树例题,并提供对应的解题思路和代码实现。
1. 二叉树的遍历二叉树的遍历是二叉树操作中最基础的操作。
它分为三种遍历方式:前序遍历、中序遍历和后序遍历。
其中,前序遍历是按照“根左右”顺序遍历,中序遍历是按照“左根右”顺序遍历,后序遍历是按照“左右根”顺序遍历。
遍历的实现方式主要有两种:递归和非递归。
递归实现比较简单,非递归实现可以利用栈来实现。
以下是前序遍历的递归实现:void preorderTraversal(TreeNode* root) {if (root != nullptr) {cout << root->val << ' ';preorderTraversal(root->left);preorderTraversal(root->right);}}以下是前序遍历的非递归实现:void preorderTraversal(TreeNode* root) {if (root == nullptr) return;stack<TreeNode*> st;st.push(root);while (!st.empty()) {TreeNode* node = st.top();st.pop();cout << node->val << ' ';if (node->right != nullptr) st.push(node->right);if (node->left != nullptr) st.push(node->left);}}2. 二叉树的最大深度二叉树的最大深度是指从根节点到叶子节点的最长路径上的节点数。
求二叉树的最大深度可以使用递归或BFS(广度优先搜索)实现。
以下是递归实现:int maxDepth(TreeNode* root) {if (root == nullptr) return 0;int leftDepth = maxDepth(root->left);int rightDepth = maxDepth(root->right);return 1 + max(leftDepth, rightDepth);}以下是BFS实现:int maxDepth(TreeNode* root) {if (root == nullptr) return 0;int depth = 0;queue<TreeNode*> q;q.push(root);while (!q.empty()) {int size = q.size();depth++;for (int i = 0; i < size; i++) {TreeNode* node = q.front();q.pop();if (node->left != nullptr) q.push(node->left);if (node->right != nullptr) q.push(node->right);}}return depth;}3. 判断两个二叉树是否相同判断两个二叉树是否相同可以通过递归实现。
二叉树的创建与遍历的实验总结引言二叉树是一种重要的数据结构,在计算机科学中有着广泛的应用。
了解二叉树的创建和遍历方法对于数据结构的学习和算法的理解至关重要。
本文将对二叉树的创建和遍历进行实验,并总结相应的经验和思考。
二叉树的定义在开始实验之前,我们首先需要了解二叉树的定义和基本概念。
二叉树是一种每个节点最多拥有两个子节点的树形结构。
每个节点包含一个值和指向其左右子节点的指针。
根据节点的位置,可以将二叉树分为左子树和右子树。
创建二叉树二叉树的创建可以采用多种方法,包括手动创建和通过编程实现。
在实验中,我们主要关注通过编程方式实现二叉树的创建。
1. 递归方法递归是一种常用的创建二叉树的方法。
通过递归,我们可以从根节点开始,逐层创建左子树和右子树。
具体步骤如下:1.创建一个空节点作为根节点。
2.递归地创建左子树。
3.递归地创建右子树。
递归方法的代码实现如下所示:class TreeNode:def __init__(self, value):self.value = valueself.left = Noneself.right = Nonedef create_binary_tree(values):if not values:return None# 使用队列辅助创建二叉树queue = []root = TreeNode(values[0])queue.append(root)for i in range(1, len(values)):node = TreeNode(values[i])# 当前节点的左子节点为空,则将新节点作为左子节点if not queue[0].left:queue[0].left = node# 当前节点的右子节点为空,则将新节点作为右子节点elif not queue[0].right:queue[0].right = node# 当前节点的左右子节点已经齐全,可以从队列中删除该节点queue.pop(0)# 将新节点添加到队列中,下一次循环时可以使用该节点queue.append(node)return root2. 非递归方法除了递归方法,我们还可以使用非递归方法创建二叉树。
二叉树的前序、后序的递归、非递归遍历算法学生姓名:贺天立指导老师:湛新霞摘要本课程设计主要解决树的前序、后序的递归、非递归遍历算法,层次序的非递归遍历算法的实现。
在课程设计中,系统开发平台为Windows 2000,程序设计设计语言采用Visual C++,程序运行平台为Windows 98/2000/XP。
用除递归算法前序,后续,中序遍历树外还通过非递归的算法遍历树。
程序通过调试运行,初步实现了设计目标,并且经过适当完善后,将可以应用在商业中解决实际问题。
关键词程序设计;C++;树的遍历;非递归遍历1 引言本课程设计主要解决树的前序、后序的递归、非递归遍历算法,层次序的非递归遍历算法的实现。
1.1课程设计的任务构造一棵树并输入数据,编写三个函数,非别是树的前序递归遍历算法、树的后序递归遍历算法、树的非递归中序遍历算法(这里的非递归以中序为例)。
在主程序中调用这三个函数进行树的遍历,观察用不同的遍历方法输出的数据的顺序和验证递归与非递归输出的数据是否一样。
1.2课程设计的性质由要求分析知,本设计主要要求解决树的前序、后序的递归、非递归遍历算法,层次序的非递归遍历算法的实现。
所以设计一个良好的前序、后序的递归、非递归遍历算法非常重要。
1.3课程设计的目的在程序设计中,可以用两种方法解决问题:一是传统的结构化程序设计方法,二是更先进的面向对象程序设计方法[1]。
利用《数据结构》课程的相关知识完成一个具有一定难度的综合设计题目,利用C语言进行程序设计。
巩固和加深对线性表、栈、队列、字符串、树、图、查找、排序等理论知识的理解;掌握现实复杂问题的分析建模和解决方法(包括问题描述、系统分析、设计建模、代码实现、结果分析等);提高利用计算机分析解决综合性实际问题的基本能力。
树的遍历分为前序、中序和后序,可以用递归算法实现树的三种遍历。
除了递归外还可以构造栈,利用出栈和入栈来实现树的前序遍历、中序遍历和后序遍历。
浅析一种二叉树非递归遍历算法的C语言实现论文一种二叉树非递归遍历算法的C语言实现论文导读:本论文是一篇关于一种二叉树非递归遍历算法的C语言实现的优秀论文范文,对正在写有关于递归论文的写有一定的参考和指导作用,摘要:针对二叉树的链式存储结构,分析了二叉树的各种遍历算法,探讨了递归算法的递推消除理由,提出了一种改善的非递归遍历算法并用C语言予以实现。
关键词:二叉树;遍历算法;非递归;C语言实现1009-3044(2014)01-0223-031 概述树形结构是一种非常常见的数据结构,而二叉树又是其中最重要的一种树形结构。
二叉树的遍历是指按照一定的规则和次序将二叉树中的每一个结点都访问一次,既不能重复,也不能漏掉。
一般而言,对二叉树的遍历有前序遍历、中序遍历、后序遍历和按层遍历等几种方式。
在具体的算法设计上,以上遍历方式一般采取递归算法来实现,该文将探讨采用非递归算法来实现二叉树的遍历。
2 二叉树的数据结构描述二叉树作为一种非线性结构,每个结点最多有一个双亲结点和两个子结点。
二叉树可以采用顺序存储结构和链式存储结构。
对于完全二叉树而言,采用顺序存储是非常方便并且节省空间的,但是对于大部分的非完全二叉树而言,采用顺序存储将导致空间浪费严重且结构混乱、效率低下。
因此,更多的时候,大家都更愿意用链式存储结构来表示二叉树,这样结构更加清晰,尤其是对于一种二叉树非递归遍历算法的C语言实现由写论文的好帮手.zbjy.提供,.左右子树的描述和双亲节点的描述更加方便。
该文中拟采用链式结构来表示二叉树。
用链式存储结构来表示二叉树,一个结点至少由3个域组成,即数据域、左子结点域和右子结点域(如图1所示)。
3 二叉树的遍历及递归算法实现3.1 二叉树的遍历二叉树的遍历就是一个不漏的访问树中的每个结点,同时也不能重复。
所谓“访问”,就是指对结点的数据域进行某种操作,比如说读取、删除、更新、求该节点深度等等。
对于二叉树中的任意一个部分,都可以把它看作三部分,根节点、左子树、右子树,我们用D表示访问跟结点,用L表示遍历左子树,用R表示遍历右子树,则共有以下6种遍历方式[1]。
先序遍历二叉树的算法非递归算法一、引言二叉树是一种常见的数据结构,其遍历方式包括先序遍历、中序遍历和后序遍历。
先序遍历是一种常用的遍历方式,它按照根节点-左子树-右子树的顺序访问每个节点。
在递归实现先序遍历二叉树的基础上,非递归算法的出现使得算法的实现更为简洁和高效。
二、非递归算法原理非递归算法的实现原理基于栈数据结构。
我们首先将根节点入栈,然后不断弹出栈顶元素并访问,同时将右子树和左子树分别入栈。
当栈为空时,表示遍历完成。
这种方法避免了递归调用可能导致的堆栈溢出问题,同时提高了算法的效率。
三、非递归算法实现以下是用Python实现的非递归先序遍历二叉树的算法:```pythondefpreorder_traversal_non_recursive(node):ifnodeisNone:return#将当前节点入栈stack.append(node)#当栈不为空时,不断弹出栈顶元素并访问whilestack:curr=stack.pop()#弹出栈顶元素print(curr.value)#访问当前节点#将右子节点入栈ifcurr.right:stack.append(curr.right)#将左子节点入栈ifcurr.left:stack.append(curr.left)```四、算法应用与讨论非递归算法的应用范围广泛,不仅可以应用于二叉树的遍历,还可以应用于二叉树的创建、插入、删除等操作。
在实际应用中,我们可以通过Python中的列表或者类来实现栈数据结构,进而实现非递归算法。
此外,非递归算法还可以与其他算法结合,如深度优先搜索(DFS)和广度优先搜索(BFS),以实现更复杂的数据处理任务。
五、总结非递归先序遍历二叉树的算法是一种实用的技术,它能够简化代码、提高效率并避免堆栈溢出问题。
通过使用栈数据结构,我们可以轻松地实现非递归算法,并将其应用于各种二叉树操作中。
这种技术对于理解和应用二叉树数据结构具有重要的意义。
C++⼆叉树的先序,中序,后序遍历三种遍历⽅式都分为递归与⾮递归的⽅式。
三种遍历⽅式的递归思想相同。
后序遍历⾮递归⽅法分为两种,具体见代码。
构造⽅式:1 #include<iostream>2 #include<stack>3using namespace std;45 typedef struct BiTNode{6char data;7int lvisited,rvisited;//左、右孩⼦是否访问过,1表⽰已访问(此项只在后序⾮递归2算法中需要)8struct BiTNode *lchild,*rchild;9 }BiTNode,*BiTree;1011void InitBiTree(BiTree &T)//构造空⼆叉树12 {13 T=NULL;14 }15void CreateBiTree(BiTree &T)//⽣成⼆叉树16 {17char ch;18 cin>>ch;19if(ch=='0')//0代表空20 T=NULL;21else22 {23 T=(BiTree)malloc(sizeof(BiTNode));//⽣成根结点24if(!T)25 {26 cout<<"⽣成结点错误!"<<endl;27return;28 }29 T->data=ch;30 T->lvisited=0;31 T->rvisited=0;32 CreateBiTree(T->lchild);33 CreateBiTree(T->rchild);34 }35 }三种遍历⽅式代码:1void PreOrder(BiTree T)//先序递归遍历2 {3if(T!=NULL)4 {5 cout<<T->data<<"";6 PreOrder(T->lchild);7 PreOrder(T->rchild);8 }9 }10void SqlPreOrder(BiTree T)//先序⾮递归遍历11 {12 stack<BiTree> s;13 BiTree p=T;14while(p || !s.empty())15 {16if(p)17 {18 cout<<p->data<<"";19 s.push(p);20 p=p->lchild;21 }22else23 {24 p=s.top();25 p=p->rchild;26 s.pop();27 }28 }29 }30313233void InOrder(BiTree T)//中序递归遍历34 {35if(T!=NULL)36 {37 InOrder(T->lchild);38 cout<<T->data<<"";39 InOrder(T->rchild);40 }41 }42void SqInOrder(BiTree T)//中序⾮递归遍历43 {44 stack<BiTree> s;45 BiTree p=T;46while(p || !s.empty())47if(p)48 {49 s.push(p);50 p=p->lchild;51 }52else53 {54 p=s.top();55 cout<<p->data<<"";56 s.pop();57 p=p->rchild;58 }59 }60616263void PostOrder(BiTree T)//后序递归遍历64 {65if(T!=NULL)66 {67 PostOrder(T->lchild);68 PostOrder(T->rchild);69 cout<<T->data<<"";70 }71 }7273//后序⾮递归遍历1思路:因为后序⾮递归遍历⼆叉树的顺序是先访问左⼦树,再访问后⼦树,最后 74//访问根结点。
数据结构(双语)——项目文档报告用递归、非递归两种方法遍历二叉树专业:计算机科学与技术班级:指导教师:姓名:学号:目录一、设计思想 (03)二、算法流程图 (04)三、源代码 (06)四、运行结果 (12)五、遇到的问题及解决 (14)六、心得体会 (15)一、设计思想1.递归:(1)主函数main()主程序要包括:定义的二叉树T、建树函数、先序遍历函数、中序遍历函数、后序遍历函数。
(2)建树函数定义一个输入的数是字符型的,当ch为空时,T就为空值,否则的话就分配空间给T,T就指向它的结点,然后左指针域指向左孩子,右指针指向右孩子,若还有,继续调用,依次循环下去,直到ch遇到空时,结束。
最后要返回建立的二叉树T。
(3)先序遍历函数根据先序遍历规则,当T为非空时,先输出结点处的数据,指针指向左、右孩子,依次进行下去。
(4) 中序遍历函数根据中序遍历规则,当T为非空时,先左指针指向左孩子数据,然后输出结点处的数据,再右指针指向右孩子,依次进行下去。
(5)后序遍历函数根据后序遍历规则,当T为非空时,先右指针指向右孩子,然后左指针指向左孩子,最后输出结点处的数据,依次进行下去。
2.非递归:(1)跟递归遍历二叉树的前提一样,首先应该创建一个二叉树,同样使用先序递归的方式创建二叉树。
(2)然后是中序,先序,后序非递归遍历二叉树。
(3)中序非递归遍历二叉树的思想是:首先是根节点压栈,当根节点的左子树不是空的时候,左子树压栈。
直到左子树为空的时候,不再压栈。
将栈顶元素出栈,访问栈顶元素,并将栈顶的右子树进栈。
当右子树的左子树不是空的时候,左子树一直进栈,直到左子树为空,则不再进栈。
重复上面的操作,直到栈空的时候。
(4)先序非递归遍历二叉树的思想是:首先是根节点进栈,然后当栈不为空的时候,将栈顶元素出栈,然后访问。
同时将出栈元素的右子树进栈,左子树进栈。
重复上面的操作,直到栈为空。
(5)后序非递归遍历二叉树的思想:首先是根节点进栈,当根节点的左子树不为空的时候,左子树进栈,直到左为空的时候,左子树不再进栈。
指针指向的是右子树,当右子树为空的时候,直接访问根节点。
当右子树不为空的时候,则右子树的指针进栈,当右子树的左子树不为空的时候,则左也进栈,直到左为空。
重复上面的操作,直到栈为空的时候,则遍历树完成。
二、算法流程图1.递归2.非递归三、源代码1.递归#include "stdio.h"#include "conio.h"#include <stdlib.h>#include<stack>typedef struct node{char data;struct node *lchild, *rchild;}BinTnode;typedef BinTnode * BinTree; //定义二叉树类型的指针/*先序创建二叉树*/int CreateBinTree(BinTree *T){char ch;*T=(BinTree)malloc(sizeof(BinTnode));if(!*T) printf("overflow");do{ch=getchar();if(ch==' '){ *T=NULL;return 0;}else{(*T)->data=ch;CreateBinTree(&((*T)->lchild));CreateBinTree(&((*T)->rchild));return 1;}}while(ch!='\0');}/*中序递归遍历*/void InorderTransverse(BinTree s){if (s){InorderTransverse(s->lchild);printf("%c", s->data);InorderTransverse(s->rchild);}}//先序递归遍历二叉树void PreOrderTranverseTree(BinTree s){if (s){printf("%c", s->data);PreOrderTranverseTree(s->lchild);PreOrderTranverseTree(s->rchild);}}//后序递归遍历二叉树void PostOrderTranverseTree(BinTree s){if (s){PreOrderTranverseTree(s->lchild);PreOrderTranverseTree(s->rchild);printf("%c", s->data);}}/*主方法*/void main(){BinTree T;printf("请按照先序的顺序输入要创建的树:\n");CreateBinTree(&T); /*中序序列创建二叉树*/printf("中序递归遍历的序列是:");InorderTransverse(T);printf("\n");//先序递归遍历printf("先序递归遍历的序列是:");PreOrderTranverseTree(T);printf("\n");//后序递归遍历printf("后序递归遍历的序列是:");PostOrderTranverseTree(T);printf("\n");}2.非递归#include "stdio.h"#include "conio.h"#include <stack>#include <stdlib.h>typedef struct node{char data;struct node *lchild, *rchild;}BinTnode;typedef BinTnode * BinTree; //定义二叉树类型的指针typedef struct{BinTree data[100];int top;}SeqStack;void initStack(SeqStack *S){S->top =-1;}void Push(SeqStack *S,BinTree x){if(S->top==100-1){printf("the stack is overflow");}else {S->top=S->top+1;S->data[S->top]=x;}}int Pop(SeqStack *S,BinTree *p){if(S->top==-1){printf("the stack is underflow");return 0;}else {*p=S->data[S->top];--S->top;return 1;}int EmptyStack(SeqStack S){if(S.top==-1) return 1;else return 0; /* 栈不空的情况*/}int GetTop(SeqStack S,BinTree *p){if(S.top==-1){printf("the stack is empty");return 0;}else {*p=S.data[S.top];return 1;}}char visit(BinTree p){return (*p).data;}/*创建二叉树*/int CreateBinTree(BinTree *T){char ch;*T=(BinTree)malloc(sizeof(BinTnode)); if(!*T) printf("overflow");else{do{ch=getchar();if(ch!=' '){*T=NULL;return 0;}else{(*T)->data=ch;CreateBinTree(&((*T)->lchild));CreateBinTree(&((*T)->rchild));return 1;}}while(ch!='\0');}}/*中序非递归遍历*/void InorderTransverse(BinTree T){SeqStack S;BinTree p;initStack(&S);//初始化栈printf("中序非递归序列是:");Push(&S,T); //根指针进栈 T为指向二叉树的指针while(!EmptyStack(S)){ //栈不是空的情况while(GetTop(S,&p) && p)Push(&S,p->lchild); //gettop得到的结果也必须是一棵子树才行 ,进栈应该进的是树根的指针Pop(&S,&p);if(!EmptyStack(S)){//printf("%c",visit(p));Pop(&S,&p);printf("%c",visit(p));Push(&S,p->rchild);}}}/*先序非递归遍历*/void PreorderTransverse(BinTree T){SeqStack S;BinTree p;initStack(&S);//初始化栈Push(&S,T); //根指针进栈 T为指向二叉树的指针printf("先序非递归序列是:");while(!EmptyStack(S)){Pop(&S,&p); //根节点出栈if(p!=NULL){printf("%c",visit(p));Push(&S,p->rchild);Push(&S,p->lchild);}}}/*后序非递归遍历*/void PostorderTransverse(BinTree T){SeqStack S;BinTree p,q;initStack(&S);//初始化栈p=T;printf("后序非递归序列是:");while(p ||!EmptyStack(S)){ //跳出while循环的原因是因为左子树或者右子树为空了if(p!=q){while(p!=NULL){Push(&S,p);if(p->lchild!=NULL)p=p->lchild;elsep=p->rchild;}}if(EmptyStack(S)) break;GetTop(S,&q);if(q->rchild==p){ //进栈的是右子树Pop(&S,&p);printf("%c",visit(p));p=q;}else{p=q->rchild;}}}/*主方法*/void main(){BinTree T;printf("请按照先序的顺序输入创建的树:\n");/*创建树*/CreateBinTree(&T);//中序非递归遍历InorderTransverse(T);printf("\n");//先序非递归遍历PreorderTransverse(T);printf("\n");//后序非递归遍历PostorderTransverse(T);}四、运行结果1.递归输入结果2.非递归输入结果五、遇到的问题及解决经过一个星期的写代码,我遇到了很多问题,并一一解决了,比如:1.创建二叉树时:void createBiTree(BiTNode *T)和void createBiTree(BiTNode *&T)没分清楚区别。