第六章二叉树中序遍历递归算法演示

合集下载

二叉树的遍历及常用算法

二叉树的遍历及常用算法

⼆叉树的遍历及常⽤算法⼆叉树的遍历及常⽤算法遍历的定义:按照某种次序访问⼆叉树上的所有结点,且每个节点仅被访问⼀次;遍历的重要性:当我们需要对⼀颗⼆叉树进⾏,插⼊,删除,查找等操作时,通常都需要先遍历⼆叉树,所有说:遍历是⼆叉树的基本操作;遍历思路:⼆叉树的数据结构是递归定义(每个节点都可能包含相同结构的⼦节点),所以遍历也可以使⽤递归,即结点不为空则继续递归调⽤每个节点都有三个域,数据与,左孩⼦指针和右孩⼦之指针,每次遍历只需要读取数据,递归左⼦树,递归右⼦树,这三个操作三种遍历次序:根据访问三个域的不同顺序,可以有多种不同的遍历次序,⽽通常对于⼦树的访问都按照从左往右的顺序;设:L为遍历左⼦树,D为访问根结点,R为遍历右⼦树,且L必须位于R的前⾯可以得出以下三种不同的遍历次序:先序遍历操作次序为DLR,⾸先访问根结点,其次遍历根的左⼦树,最后遍历根右⼦树,对每棵⼦树同样按这三步(先根、后左、再右)进⾏中序遍历操作次序为LDR,⾸先遍历根的左⼦树,其次访问根结点,最后遍历根右⼦树,对每棵⼦树同样按这三步(先左、后根、再右)进⾏后序遍历操作次序为LRD,⾸先遍历根的左⼦树,其次遍历根的右⼦树,最后访问根结点,对每棵⼦树同样按这三步(先左、后右、最后根)进⾏层次遍历层次遍历即按照从上到下从左到右的顺序依次遍历所有节点,实现层次遍历通常需要借助⼀个队列,将接下来要遍历的结点依次加⼊队列中;遍历的应⽤“遍历”是⼆叉树各种操作的基础,可以在遍历过程中对结点进⾏各种操作,如:对于⼀棵已知⼆叉树求⼆叉树中结点的个数求⼆叉树中叶⼦结点的个数;求⼆叉树中度为1的结点个数求⼆叉树中度为2的结点个数5求⼆叉树中⾮终端结点个数交换结点左右孩⼦判定结点所在层次等等...C语⾔实现:#include <stdio.h>//⼆叉链表数据结构定义typedef struct TNode {char data;struct TNode *lchild;struct TNode *rchild;} *BinTree, BinNode;//初始化//传⼊⼀个指针令指针指向NULLvoid initiate(BinTree *tree) {*tree = NULL;}//创建树void create(BinTree *BT) {printf("输⼊当前结点值: (0则创建空节点)\n");char data;scanf(" %c", &data);//连续输⼊整形和字符时.字符变量会接受到换⾏,所以加空格if (data == 48) {*BT = NULL;return;} else {//创建根结点//注意开辟的空间⼤⼩是结构体的⼤⼩⽽不是结构体指针⼤⼩,写错了不会⽴马产⽣问题,但是后续在其中存储数据时极有可能出现内存访问异常(飙泪....) *BT = malloc(sizeof(struct TNode));//数据域赋值(*BT)->data = data;printf("输⼊节点 %c 的左孩⼦ \n", data);create(&((*BT)->lchild));//递归创建左⼦树printf("输⼊节点 %c 的右孩⼦ \n", data);create(&((*BT)->rchild));//递归创建右⼦树}}//求双亲结点(⽗结点)BinNode *Parent(BinTree tree, char x) {if (tree == NULL)return NULL;else if ((tree->lchild != NULL && tree->lchild->data == x) || (tree->rchild != NULL && tree->rchild->data == x))return tree;else{BinNode *node1 = Parent(tree->lchild, x);BinNode *node2 = Parent(tree->rchild, x);return node1 != NULL ? node1 : node2;}}//先序遍历void PreOrder(BinTree tree) {if (tree) {//输出数据printf("%c ", tree->data);//不为空则按顺序继续递归判断该节点的两个⼦节点PreOrder(tree->lchild);PreOrder(tree->rchild);}}//中序void InOrder(BinTree tree) {if (tree) {InOrder(tree->lchild);printf("%c ", tree->data);InOrder(tree->rchild);}}//后序void PostOrder(BinTree tree) {if (tree) {PostOrder(tree->lchild);PostOrder(tree->rchild);printf("%c ", tree->data);}}//销毁结点递归free所有节点void DestroyTree(BinTree *tree) {if (*tree != NULL) {printf("free %c \n", (*tree)->data);if ((*tree)->lchild) {DestroyTree(&((*tree)->lchild));}if ((*tree)->rchild) {DestroyTree(&((*tree)->rchild));}free(*tree);*tree = NULL;}}// 查找元素为X的结点使⽤的是层次遍历BinNode *FindNode(BinTree tree, char x) {if (tree == NULL) {return NULL;}//队列BinNode *nodes[1000] = {};//队列头尾位置int front = 0, real = 0;//将根节点插⼊到队列尾nodes[real] = tree;real += 1;//若队列不为空则继续while (front != real) {//取出队列头结点输出数据BinNode *current = nodes[front];if (current->data == x) {return current;}front++;//若当前节点还有⼦(左/右)节点则将结点加⼊队列if (current->lchild != NULL) {nodes[real] = current->lchild;real++;}if (current->rchild != NULL) {nodes[real] = current->rchild;real++;}}return NULL;}//层次遍历// 查找元素为X的结点使⽤的是层次遍历void LevelOrder(BinTree tree) {if (tree == NULL) {return;}//队列BinNode *nodes[1000] = {};//队列头尾位置int front = 0, real = 0;//将根节点插⼊到队列尾nodes[real] = tree;real += 1;//若队列不为空则继续while (front != real) {//取出队列头结点输出数据BinNode *current = nodes[front];printf("%2c", current->data);front++;//若当前节点还有⼦(左/右)节点则将结点加⼊队列if (current->lchild != NULL) {nodes[real] = current->lchild;real++;}if (current->rchild != NULL) {nodes[real] = current->rchild;real++;}}}//查找x的左孩⼦BinNode *Lchild(BinTree tree, char x) {BinTree node = FindNode(tree, x);if (node != NULL) {return node->lchild;}return NULL;}//查找x的右孩⼦BinNode *Rchild(BinTree tree, char x) {BinTree node = FindNode(tree, x);if (node != NULL) {return node->rchild;}return NULL;}//求叶⼦结点数量int leafCount(BinTree *tree) {if (*tree == NULL)return 0;//若左右⼦树都为空则该节点为叶⼦,且后续不⽤接续递归了else if (!(*tree)->lchild && !(*tree)->rchild)return 1;else//若当前结点存在⼦树,则递归左右⼦树, 结果相加return leafCount(&((*tree)->lchild)) + leafCount(&((*tree)->rchild));}//求⾮叶⼦结点数量int NotLeafCount(BinTree *tree) {if (*tree == NULL)return 0;//若该结点左右⼦树均为空,则是叶⼦,且不⽤继续递归else if (!(*tree)->lchild && !(*tree)->rchild)return 0;else//若当前结点存在左右⼦树,则是⾮叶⼦结点(数量+1),在递归获取左右⼦树中的⾮叶⼦结点,结果相加 return NotLeafCount(&((*tree)->lchild)) + NotLeafCount(&((*tree)->rchild)) + 1;}//求树的⾼度(深度)int DepthCount(BinTree *tree) {if (*tree == NULL)return 0;else{//当前节点不为空则深度+1 在加上⼦树的⾼度,int lc = DepthCount(&((*tree)->lchild)) + 1;int rc = DepthCount(&((*tree)->rchild)) + 1;return lc > rc?lc:rc;// 取两⼦树深度的最⼤值 }}//删除左⼦树void RemoveLeft(BinNode *node){if (!node)return;if (node->lchild)DestroyTree(&(node->lchild));node->lchild = NULL;}//删除右⼦树void RemoveRight(BinNode *node){if (!node)return;if (node->rchild)DestroyTree(&(node->rchild));node->rchild = NULL;}int main() {BinTree tree;create(&tree);BinNode *node = Parent(tree, 'G');printf("G的⽗结点为%c\n",node->data);BinNode *node2 = Lchild(tree, 'D');printf("D的左孩⼦结点为%c\n",node2->data);BinNode *node3 = Rchild(tree, 'D');printf("D的右孩⼦结点为%c\n",node3->data);printf("先序遍历为:");PreOrder(tree);printf("\n");printf("中序遍历为:");InOrder(tree);printf("\n");printf("后序遍历为:");PostOrder(tree);printf("\n");printf("层次遍历为:");LevelOrder(tree);printf("\n");int a = leafCount(&tree);printf("叶⼦结点数为%d\n",a);int b = NotLeafCount(&tree);printf("⾮叶⼦结点数为%d\n",b);int c = DepthCount(&tree);printf("深度为%d\n",c);//查找F节点BinNode *node4 = FindNode(tree,'C');RemoveLeft(node4);printf("删除C的左孩⼦后遍历:");LevelOrder(tree);printf("\n");RemoveRight(node4);printf("删除C的右孩⼦后遍历:");LevelOrder(tree);printf("\n");//销毁树printf("销毁树 \n");DestroyTree(&tree);printf("销毁后后遍历:");LevelOrder(tree);printf("\n");printf("Hello, World!\n");return 0;}测试:测试数据为下列⼆叉树:运⾏程序复制粘贴下列内容:ABDGHECKFIJ特别感谢:iammomo。

中序遍历例子

中序遍历例子

中序遍历例子中序遍历是二叉树遍历的一种方式,它的遍历顺序是先遍历左子树,然后访问根节点,最后遍历右子树。

下面是一些例子,展示了如何使用中序遍历来遍历二叉树。

例子1:假设有一个二叉树如下所示:```1/ \2 3/ \4 5```按照中序遍历的顺序,我们应该先遍历左子树,然后访问根节点,最后遍历右子树。

所以,按照中序遍历的顺序,上面的二叉树应该输出4 2 5 1 3。

例子2:如果我们有一个更复杂的二叉树:```5/ \3 8/ \ \1 4 9```按照中序遍历的顺序,应该输出1 3 4 5 8 9。

例子3:如果二叉树为空树,那么中序遍历的结果应该是空。

例子4:对于只有一个根节点的二叉树,中序遍历的结果就是根节点本身。

例子5:如果二叉树的左子树为空,那么中序遍历的结果就是根节点和右子树的遍历结果按顺序排列。

例子6:如果二叉树的右子树为空,那么中序遍历的结果就是左子树的遍历结果和根节点按顺序排列。

例子7:对于一个完全二叉树,中序遍历的结果应该是按照从左到右的顺序输出所有节点。

例子8:对于一颗平衡二叉树,中序遍历的结果应该是按照从小到大的顺序输出所有节点。

例子9:对于一颗非平衡二叉树,中序遍历的结果可能是乱序的。

例子10:对于一颗二叉搜索树,中序遍历的结果应该是按照从小到大的顺序输出所有节点。

以上是一些使用中序遍历来遍历二叉树的例子。

通过这些例子,我们可以更好地理解中序遍历的概念和应用。

中序遍历是一种非常重要的二叉树遍历方式,它可以帮助我们按照一定的规则来访问二叉树的节点,从而实现对二叉树的各种操作。

二叉树遍历典型例题

二叉树遍历典型例题

二叉树遍历典型例题正文:二叉树的遍历是指按照某种顺序访问二叉树中的所有节点。

常见的二叉树遍历方式有三种:前序遍历、中序遍历和后序遍历。

下面将以一个典型的例题来介绍这三种遍历方式的应用。

假设有一个二叉树如下所示:```1/2 3/4 5 6```首先介绍前序遍历。

前序遍历的顺序是先访问根节点,然后分别遍历左子树和右子树。

对于上面的二叉树,前序遍历的结果是1, 2, 4, 3, 5, 6。

接下来是中序遍历。

中序遍历的顺序是先遍历左子树,然后访问根节点,最后遍历右子树。

对于上面的二叉树,中序遍历的结果是2, 4, 1, 5, 3, 6。

最后是后序遍历。

后序遍历的顺序是先遍历左子树,然后遍历右子树,最后访问根节点。

对于上面的二叉树,后序遍历的结果是4, 2, 5, 6, 3, 1。

以上就是三种常见的二叉树遍历方式。

在实际应用中,二叉树的遍历经常用于查找、删除、插入等操作。

例如,在前序遍历中,可以用来复制一棵二叉树;在中序遍历中,可以用来对树进行排序;在后序遍历中,可以用来释放二叉树的内存等。

除了以上介绍的三种遍历方式,还存在一种更特殊的遍历方式,即层序遍历。

层序遍历是逐层访问二叉树节点的方式,从上到下、从左到右。

对于上面的二叉树,层序遍历的结果是1, 2, 3, 4, 5, 6。

在实际应用中,根据具体的问题要求,选择合适的遍历方式能够更加高效地解决问题。

因此,对于二叉树的遍历问题,我们需要熟练掌握各种遍历方式的特点和应用场景,以便于在实际问题中灵活运用。

二叉树遍历(前中后序遍历,三种方式)

二叉树遍历(前中后序遍历,三种方式)

⼆叉树遍历(前中后序遍历,三种⽅式)⽬录刷题中碰到⼆叉树的遍历,就查找了⼆叉树遍历的⼏种思路,在此做个总结。

对应的LeetCode题⽬如下:,,,接下来以前序遍历来说明三种解法的思想,后⾯中序和后续直接给出代码。

⾸先定义⼆叉树的数据结构如下://Definition for a binary tree node.struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}};前序遍历,顺序是“根-左-右”。

使⽤递归实现:递归的思想很简单就是我们每次访问根节点后就递归访问其左节点,左节点访问结束后再递归的访问右节点。

代码如下:class Solution {public:vector<int> preorderTraversal(TreeNode* root) {if(root == NULL) return {};vector<int> res;helper(root,res);return res;}void helper(TreeNode *root, vector<int> &res){res.push_back(root->val);if(root->left) helper(root->left, res);if(root->right) helper(root->right, res);}};使⽤辅助栈迭代实现:算法为:先把根节点push到辅助栈中,然后循环检测栈是否为空,若不空,则取出栈顶元素,保存值到vector中,之后由于需要想访问左⼦节点,所以我们在将根节点的⼦节点⼊栈时要先经右节点⼊栈,再将左节点⼊栈,这样出栈时就会先判断左⼦节点。

代码如下:class Solution {public:vector<int> preorderTraversal(TreeNode* root) {if(root == NULL) return {};vector<int> res;stack<TreeNode*> st;st.push(root);while(!st.empty()){//将根节点出栈放⼊结果集中TreeNode *t = st.top();st.pop();res.push_back(t->val);//先⼊栈右节点,后左节点if(t->right) st.push(t->right);if(t->left) st.push(t->left);}return res;}};Morris Traversal⽅法具体的详细解释可以参考如下链接:这种解法可以实现O(N)的时间复杂度和O(1)的空间复杂度。

前序后序中序详细讲解

前序后序中序详细讲解

前序后序中序详细讲解1.引言1.1 概述在数据结构与算法中,前序、中序和后序是遍历二叉树的三种基本方式之一。

它们是一种递归和迭代算法,用于按照特定的顺序访问二叉树的所有节点。

通过遍历二叉树,我们可以获取有关树的结构和节点之间关系的重要信息。

前序遍历是指先访问根节点,然后递归地访问左子树,最后递归地访问右子树。

中序遍历是指先递归地访问左子树,然后访问根节点,最后递归地访问右子树。

后序遍历是指先递归地访问左子树,然后递归地访问右子树,最后访问根节点。

它们的不同之处在于访问根节点的时机不同。

前序遍历可以帮助我们构建二叉树的镜像,查找特定节点,或者获取树的深度等信息。

中序遍历可以帮助我们按照节点的大小顺序输出树的节点,或者查找二叉搜索树中的某个节点。

后序遍历常用于删除二叉树或者释放二叉树的内存空间。

在实际应用中,前序、中序和后序遍历算法有着广泛的应用。

它们可以用于解决树相关的问题,例如在Web开发中,树结构的遍历算法可以用于生成网页导航栏或者搜索树结构中的某个节点。

在图像处理中,前序遍历可以用于图像压缩或者图像识别。

另外,前序和后序遍历算法还可以用于表达式求值和编译原理中的语法分析等领域。

综上所述,前序、中序和后序遍历算法是遍历二叉树的重要方式,它们在解决各种与树有关的问题中扮演着关键的角色。

通过深入理解和应用这些遍历算法,我们可以更好地理解和利用二叉树的结构特性,并且能够解决更加复杂的问题。

1.2文章结构文章结构是指文章中各个部分的布局和组织方式。

一个良好的文章结构可以使读者更好地理解和理解文章的内容。

本文将详细讲解前序、中序和后序三个部分的内容和应用。

首先,本文将在引言部分概述整篇文章的内容,并介绍文章的结构和目的。

接下来,正文部分将分为三个小节,分别对前序、中序和后序进行详细讲解。

在前序讲解部分,我们将定义和解释前序的意义,并介绍前序在实际应用中的场景。

通过详细的解释和实例,读者将能更好地理解前序的概念和用途。

tree2_

tree2_

根节点有右孩子吗?
6.4.2 森林和二叉树的转换
森林和二叉树的转换
树 与 二 叉 树
6.4.3 树和森林的遍历
树的遍历
先根遍历 后跟遍历
先根遍历:RADEBCFGHK 后根遍历:DEABGHKFCR
6.3 遍历二叉树 6.4 树和森林
树的存储结构 树和森林的转换 树和森林的ห้องสมุดไป่ตู้历
6.5 6.6 6.7 6.8
树与等价问题 哈夫曼树及其应用 回溯法与树的遍历 树的计数
6.4.1 树的存储结构
双亲表示法
便于涉及双亲的操作 求结点的孩子时需要遍历整棵树
//-----------树的双亲表存储表示----------// #define MAX_TREE_SIZE 100 typedef struct PTNode { TElemType data; int parent; //双亲位置域 }PTNode; typedef struct{ PTNode nodes[MAX_TREE_SIZE]; int r,n; //根的位置和结点数 }PTree;
线索链表的存储结构
//Link==0:指针,Thread==1:线索
typedef enum {Link,Thread} PointerTag; typedef struct BiThrNode { TElemType data; struct BiThrNode *lchild,*rchild; //左右孩子指针 PointerTag LTag, RTag; //左右标志 }BiThrNode, *BiThrTree;
中序线索二叉树
NIL a + e / * b f 1 b 1 中序遍历:a+b*c-d-e/f NIL + *

非递归中序遍历二叉树课件

非递归中序遍历二叉树课件
由于在非递归实现中,我们使用栈来 模拟递归的过程,因此遍历后的结果 与递归实现相同。
04 非递归中序遍历 二叉树的复杂度 分析
时间复杂度
最好情况:O(n) 最坏情况:O(n)
平均情况:O(n)
空间复杂度
最好情况:O(1) 最坏情况:O(n)
平均情况:O(n)
05 非递归中序遍历 二叉树的优缺点
优点
01
02
03
空间效率高
非递归算法通常只需要常 数级别的额外空间,相比 之下,递归算法可能需要 更多的堆栈空间。
代码简洁
非递归算法的代码通常更 简洁,更易于理解和维护。
适合处理大型数据
由于非递归算法不需要大 量的堆栈空间,因此更适 合处理大型数据集。
缺点
编程技巧要求高
非递归算法需要更多的编程技巧, 特别是对于那些不熟悉这种技术 的人来说,理解和实现可能会比 较困难。
遍历过程
01
02
03
04
弹出栈顶元素,访问该 节点。
如果该节点右子节点存 在,将右子节点入栈。
如果该节点左子节点存 在,将左子节点入栈。
重复上述步骤,直到栈 为空。
遍历后的结果
01
中序遍历的顺序为:左子树 -> 根节点 -> 右子树。
02
非递归方法利用了栈的性质,实 现了从上到下、从左到右的遍历 顺序。
THANKS
感谢观看
栈为空。
实例二:复杂的二叉树
总结词:进阶应用
详细描述:对于复杂的二叉树,非递归中序遍历需要 更加细致的处理。由于树的形状可能不规则,我们需 要更加灵活地使用栈来处理节点之间的关系。在遍历 过程中,我们需要注意处理各种特殊情况,例如循环 引用、节点值相等的情况,以避免陷入无限循环或访 问错误的节点。此外,我们还需要注意优化算法的时 间复杂度和空间复杂度,以提高遍历的效率和准确性。

二叉树的遍历PPT-课件

二叉树的遍历PPT-课件

4 、二叉树的创建算法
利用二叉树前序遍历的结果可以非常方便地生成给定的
二叉树,具体做法是:将第一个输入的结点作为二叉树的 根结点,后继输入的结点序列是二叉树左子树前序遍历的 结果,由它们生成二叉树的左子树;再接下来输入的结点 序列为二叉树右子树前序遍历的结果,应该由它们生成二 叉树的右子树;而由二叉树左子树前序遍历的结果生成二 叉树的左子树和由二叉树右子树前序遍历的结果生成二叉 树的右子树的过程均与由整棵二叉树的前序遍历结果生成 该二叉树的过程完全相同,只是所处理的对象范围不同, 于是完全可以使用递归方式加以实现。
void createbintree(bintree *t) { char ch; if ((ch=getchar())==' ') *t=NULL; else { *t=(bintnode *)malloc(sizeof(bintnode)); /*生成二叉树的根结点*/ (*t)->data=ch; createbintree(&(*t)->lchild); /*递归实现左子树的建立*/ createbintree(&(*t)->rchild); /*递归实现右子树的建立*/ }
if (s.top>-1) { t=s.data[s.top]; s.tag[s.top]=1; t=t->rchild; }
else t=NULL; }
}
7.5 二叉树其它运算的实现
由于二叉树本身的定义是递归的,因此关于二叉树的许多 问题或运算采用递归方式实现非常地简单和自然。 1、二叉树的查找locate(t,x)
(1)对一棵二叉树中序遍历时,若我们将二叉树严
格地按左子树的所有结点位于根结点的左侧,右子树的所

二叉树的先序,中序,后序遍历例题

二叉树的先序,中序,后序遍历例题

二叉树的先序,中序,后序遍历例题二叉树的先序遍历、中序遍历和后序遍历是三种常见的遍历方式。

以下是相应的例题:1. 先序遍历以下是一个简单的二叉树,请实现先序遍历:```3/1 5/2 4 6```先序遍历的结果应该是:3,1,2,4,5,6。

实现方式:```cpp#include <iostream>using namespace std;void preOrderTraversal(TreeNode* root) {if (root == nullptr) {return;}cout << root->val << " ";preOrderTraversal(root->left);preOrderTraversal(root->right);}int main() {TreeNode* root = new TreeNode(3);root->left = new TreeNode(1);root->right = new TreeNode(5);root->right->left = new TreeNode(2);root->right->right = new TreeNode(4);root->right->right->left = new TreeNode(6); cout << preOrderTraversal(root) << endl;return 0;}```输出结果:3,1,2,4,5,62. 中序遍历以下是一个简单的二叉树,请实现中序遍历:```1/4 2/5 3 6```中序遍历的结果应该是:1,4,2,5,3,6。

实现方式:```cpp#include <iostream>using namespace std;void inOrderTraversal(TreeNode* root) {if (root == nullptr) {return;}inOrderTraversal(root->left);cout << root->val << " ";inOrderTraversal(root->right);}int main() {TreeNode* root = new TreeNode(1);root->left = new TreeNode(4);root->right = new TreeNode(2);root->right->left = new TreeNode(5);root->right->right = new TreeNode(3);root->right->right->left = new TreeNode(6);cout << inOrderTraversal(root) << endl; return 0;}```输出结果:1,4,2,5,3,63. 后序遍历以下是一个简单的二叉树,请实现后序遍历: ```2/4 6/1 3 5```后序遍历的结果应该是:2,4,6,1,3,5。

第六章树2

第六章树2

有六种遍历方法:D L R,L D R,L R D,D R L,R D L,R L D D R, R, D, L, L, 约定: R, R, 约定:先左后右,有三种遍历方法: D L R,L D R,L R D , 分别称为先序遍历,中序遍历,后序遍历
3
A,先序遍历(D L R)(前缀表示) D R 若二叉树非空 (1)访问根结点; (2)先序遍历左子树; D (3)先序遍历右子树; ; 例:先序遍历右图所示的二叉树
……
if (k== -1) T=NULL; else { } } // } // CrtBT
18
T=(BiTNode*)malloc(sizeof(BiTNode)); T->data = pre[ps]; if (k==is) T->Lchild = NULL; else CrtBT(T->Lchild, pre[], ino[], ps+1, is, k-is ); if (k=is+n-1) T->Rchild = NULL; else CrtBT(T->Rchild, pre[], ino[], ps+1+(k-is), k+1, n-(k-is)-1 );
2
2,对"二叉树"而言,可以有三条搜索路径: , 二叉树"而言,可以有三条搜索路径: 先上后下 先上后下的按层次遍历; 先左 先左(子树)后右 后右(子树)的遍历; 后右 先右 先右(子树)后左 后左(子树)的遍历. 后左
二叉树由根,左子树,右子树三部分组成 令: D:访问根结点 L:遍历左子树 R:遍历右子树 L D R
24
4,复制二叉树
(后序遍历) 后序遍历)
其基本操作为:生成一个结点. 其基本操作为:生成一个结点. T 根元素 左子树 左子树 右子树 右子树 左子树 NEWT 根元素 右子树

C语言实现二叉树的中序遍历(递归)

C语言实现二叉树的中序遍历(递归)
c语言实现二叉树的中序遍历(递归) 二叉树的前序遍历,中序遍历,后续遍历 (包括递归,非递归,共六种) 1,中序遍历(递归): #include #include struct bitnode//定义结构体 { char data; struct bitnode *lchild,*rchild; }; void later(struct bitnode *&amp;p) //前序创建树 { char ch; scanf("%c",&amp;ch); if(ch==' ') p=null; else { p=(struct bitnode *)malloc(sizeof(struct bitnode)); p->data=ch; later(p->lchild); later(p->rchild); } } void print(struct bitnode *p) //中序遍历(输出二叉树) { if(p!=null) { print(p->lchild); printf("%c",p->data); print(p->rchild); } else printf(" "); } void main()//主函数 { struct bitnode *p; later(p); print(p); } 供测试使用的数据
C语 言 实 现 二 叉 树 的 中 序 遍 历 ( 递 归 )
二叉树的前序遍历、中序遍历、后续遍历 (包括递归、非递归,共六种) 1、中序遍历(递归): #include #include struct BiTNode//定义结构体 { char data; struct BiTNode *lchild,*rchild; }; void later(struct BiTNode *&p) //前序创建树 { char ch; scanf("%c",&ch); if(ch==' ') p=NULL; else { p=(struct BiTNode *)malloc(sizeof(struct BiTNode)); p->data=ch; later(p->lchild); later(p->rchild); } } void print(struct BiTNode *p) //中序遍历(输出二叉树) { if(p!=NULL) { print(p->lchild); printf("%c",p->data); print(p->rchild); } else printf(" ");

二叉树的遍历(前序、中序、后序、已知前中序求后序、已知中后序求前序)

二叉树的遍历(前序、中序、后序、已知前中序求后序、已知中后序求前序)

⼆叉树的遍历(前序、中序、后序、已知前中序求后序、已知中后序求前序)之前的⼀篇随笔()只对⼆叉树的遍历进⾏了笼统的描述,这篇随笔重点对前、中、后序的遍历顺序进⾏分析⼆叉树的遍历⼆叉树的深度优先遍历可细分为前序遍历、中序遍历、后序遍历,这三种遍历可以⽤递归实现(本篇随笔主要分析递归实现),也可使⽤⾮递归实现的前序遍历:根节点->左⼦树->右⼦树(根->左->右)中序遍历:左⼦树->根节点->右⼦树(左->根->右)后序遍历:左⼦树->右⼦树->根节点(左->右->根)在进⾏已知两种遍历顺序求另⼀种遍历顺序前,先看⼀下不同遍历顺序对应的代码前序遍历1/* 以递归⽅式前序遍历⼆叉树 */2void PreOrderTraverse(BiTree t, int level)3 {4if (t == NULL)5 {6return ;7 }8 printf("data = %c level = %d\n ", t->data, level);9 PreOrderTraverse(t->lchild, level + 1);10 PreOrderTraverse(t->rchild, level + 1);11 }中序遍历1/* 以递归⽅式中序遍历⼆叉树 */2void PreOrderTraverse(BiTree t, int level)3 {4if (t == NULL)5 {6return ;7 }8 PreOrderTraverse(t->lchild, level + 1);9 printf("data = %c level = %d\n ", t->data, level);10 PreOrderTraverse(t->rchild, level + 1);11 }后序遍历1/* 以递归⽅式后序遍历⼆叉树 */2void PreOrderTraverse(BiTree t, int level)3 {4if (t == NULL)5 {6return ;7 }8 PreOrderTraverse(t->lchild, level + 1);9 PreOrderTraverse(t->rchild, level + 1);10 printf("data = %c level = %d\n ", t->data, level);11 }三种遍历⽅式对应的代码⼏乎相同,只是⼀条语句的位置发⽣了变化printf("data = %c level = %d\n ", t->data, level);只看⽂字和代码来理解遍历的过程是⽐较困难的,建议读者亲⾃去遍历,为了理清遍历的过程下⾯上题(图⽚来源:)前序遍历前序的遍历的特点,根节点->左⼦树->右⼦树,注意看前序的遍历的代码printf语句是放在两条递归语句之前的,所以先访问根节点G,打印G,然后访问左⼦树D,此时左⼦树D⼜作为根节点,打印D,再访问D的左⼦树AA⼜作为根节点,打印A,A没有左⼦树或者右⼦树,函数调⽤结束返回到D节点(此时已经打印出来的有:GDA)D节点的左⼦树已经递归完成,现在递归访问右⼦树F,F作为根节点,打印F,F有左⼦树访问左⼦树E,E作为根节点,打印E,(此时已经打印出来的有:GDAFE),E没有左⼦树和右⼦树,函数递归结束返回F节点,F的左⼦树已经递归完成了,但没有右⼦树,所以函数递归结束,返回D节点,D节点的左⼦树和右⼦树递归全部完成,函数递归结束返回G节点,访问G节点的右⼦树M,M作为根节点,打印M,访问M的左⼦树H,H作为根节点,打印H,(此时已经打印出来的有:GDAFEMH)H没有左⼦树和右⼦树,函数递归结束,返回M节点,M节点的左⼦树已经递归完成,访问右⼦树Z,Z作为根节点,打印Z,Z没有左⼦树和右⼦树,函数递归结束,返回M节点,M节点的左⼦树右⼦树递归全部完成,函数递归结束,返回G节点,G节点的左右⼦树递归全部完成,整个⼆叉树的遍历就结束了(MGJ,终于打完了··)前序遍历结果:GDAFEMHZ总结⼀下前序遍历步骤第⼀步:打印该节点(再三考虑还是把访问根节点这句话去掉了)第⼆步:访问左⼦树,返回到第⼀步(注意:返回到第⼀步的意思是将根节点的左⼦树作为新的根节点,就好⽐图中D是G的左⼦树但是D也是A节点和F节点的根节点)第三步:访问右⼦树,返回到第⼀步第四步:结束递归,返回到上⼀个节点前序遍历的另⼀种表述:(1)访问根节点(2)前序遍历左⼦树(3)前序遍历右⼦树(在完成第2,3步的时候,也是要按照前序遍历⼆叉树的规则完成)前序遍历结果:GDAFEMHZ中序遍历(详细遍历过程就不再赘述了,(┬_┬))中序遍历步骤第⼀步:访问该节点左⼦树第⼆步:若该节点有左⼦树,则返回第⼀步,否则打印该节点第三步:若该节点有右⼦树,则返回第⼀步,否则结束递归并返回上⼀节点(按我⾃⼰理解的中序就是:先左到底,左到不能在左了就停下来并打印该节点,然后返回到该节点的上⼀节点,并打印该节点,然后再访问该节点的右⼦树,再左到不能再左了就停下来)中序遍历的另⼀种表述:(1)中序遍历左⼦树(2)访问根节点(3)中序遍历右⼦树(在完成第1,3步的时候,要按照中序遍历的规则来完成)所以该图的中序遍历为:ADEFGHMZ后序遍历步骤第⼀步:访问左⼦树第⼆步:若该节点有左⼦树,返回第⼀步第三步:若该节点有右⼦树,返回第⼀步,否则打印该节点并返回上⼀节点后序遍历的另⼀种表述:(1)后序遍历左⼦树(2)后序遍历右⼦树(3)访问根节点(在完成1,2步的时候,依然要按照后序遍历的规则来完成)该图的后序遍历为:AEFDHZMG(读者如果在纸上遍历⼆叉树的时候,仍然容易将顺序搞错建议再回去看⼀下三种不同遍历对应的代码)进⼊正题,已知两种遍历结果求另⼀种遍历结果(其实就是重构⼆叉树)第⼀种:已知前序遍历、中序遍历求后序遍历前序遍历:ABCDEF中序遍历:CBDAEF在进⾏分析前读者需要知道不同遍历结果的特点1、前序遍历的第⼀元素是整个⼆叉树的根节点2、中序遍历中根节点的左边的元素是左⼦树,根节点右边的元素是右⼦树3、后序遍历的最后⼀个元素是整个⼆叉树的根节点(如果读者不明⽩上述三个特点,建议再回去看⼀下三种不同遍历对应的代码,并在纸上写出⼀个简单的⼆叉树的三种不同的遍历结果,以加深对三种不同遍历的理解)⽤上⾯这些特点来分析遍历结果,第⼀步:先看前序遍历A肯定是根节点第⼆步:确认了根节点,再来看中序遍历,中序遍历中根节点A的左边是CBD,右边是EF,所有可以确定⼆叉树既有左⼦树⼜有右⼦树第三步:先来分析左⼦树CBD,那么CBD谁来做A的左⼦树呢?这个时候不能直接⽤中序遍历的特点(左->根->右)得出左⼦树应该是这个样⼦因为有两种情况都满⾜中序遍历为CBD⽆法直接根据中序遍历来直接得出左⼦树的结构,这个时候就要返回到前序遍历中去观察前序遍历ABCDEF,左⼦树CBD在前序遍历中的顺序是BCD,意味着B是左⼦树的根节点(这么说可能不太好理解,换个说法就是B是A的左⼦树),得出这个结果是因为如果⼀个⼆叉树的根节点有左⼦树,那么这个左⼦树⼀定在前序遍历中⼀定紧跟着根节点(这个是⽤前序遍历的特点(根->左->右)得出的),到这⾥就可以确认B是左⼦树的根节点第四步:再观察中序遍历CBDAEF,B元素左边是C右边是D,说明B节点既有左⼦树⼜有右⼦树,左右⼦树只有⼀个元素就可以直接确定了,不⽤再返回去观察前序遍历第五步:到这⾥左⼦树的重建就已经完成了,现在重建右⼦树,因为重建右⼦树的过程和左⼦树的过程⼀模⼀样,步骤就不像上⾯写这么细了((┬_┬)),观察中序遍历右⼦树为EF,再观察前序遍历ABCDEF中右⼦树的顺序为EF,所以E为A的右⼦树,再观察中序便利中E只有右边有F,所有F为E的右⼦树,最后得到的⼆叉树是这个样⼦的所有求得的后序遍历为:CDBFEA总结⼀下上述步骤:先观察前序遍历找到根节点->观察中序遍历将根节点左边归为左⼦树元素,右边归为右⼦树元素(可能会出现只有左⼦树或者右⼦树的情况)->观察前序遍历中左\右⼦树⼏个元素的顺序,最靠前的为左\右⼦树的根节点->重复前⾯的步骤第⼆种:已知中序遍历、后序遍历求前序遍历(题还是上⾯这道)中序遍历:CBDAEF后序遍历为:CDBFEA仍然是根据不同遍历⽅式结果的特点来重构⼆叉树,过程很相似这⾥就不详细说了,后序遍历的最后⼀个元素A是根节点,在中序遍历中以根节点A作为分界将元素分为左⼦树(CBD)和右⼦树(EF),再观察后序遍历中左⼦树的顺序是CDB,可以判断出B是左⼦树的根节点(因为后序遍历是:左->右->根),再观察中序遍历,B元素左边是C右边是D,说明B节点既有左⼦树⼜有右⼦树,左右⼦树只有⼀个元素就可以直接确定了,不⽤再返回去观察后序遍历,左⼦树重建完成,现在来看右⼦树,右⼦树有两个元素EF,观察后序遍历E在F的后⾯,所以E是右⼦树的根节点,然后看中序遍历中E只有右边⼀个F元素了,即F是E的右⼦树,此时整个⼆叉树重构完成总结⼀下上述步骤:先观察后序遍历找到根节点->观察中序遍历将根节点左边归为左⼦树元素,右边归为右⼦树元素(可能会出现只有左⼦树或者右⼦树的情况)->观察后序遍历中左\右⼦树⼏个元素的顺序,最靠后的为左\右⼦树的根节点->重复前⾯的步骤注意:已知前序遍历、后序遍历⽆法求出中序遍历(因为由前序后序重构出来的⼆叉树不⽌⼀种)举个栗⼦左图这两种⼆叉树前序(BEFA)和后序(AFEB)⼀样,但对应的中序遍历结果不⼀样(左边的是AFEB右边的是BEFA),所以仅靠前序后序是重构出唯⼀的⼆叉树。

二叉树的四种遍历算法

二叉树的四种遍历算法

⼆叉树的四种遍历算法⼆叉树作为⼀种重要的数据结构,它的很多算法的思想在很多地⽅都⽤到了,⽐如STL算法模板,⾥⾯的优先队列、集合等等都⽤到了⼆叉树⾥⾯的思想,先从⼆叉树的遍历开始:看⼆叉树长什么样⼦:我们可以看到这颗⼆叉树⼀共有七个节点0号节点是根节点1号节点和2号节点是0号节点的⼦节点,1号节点为0号节点的左⼦节点,2号节点为0号节点的右⼦节点同时1号节点和2号节点⼜是3号节点、四号节点和五号节点、6号节点的双亲节点五号节点和6号节点没有⼦节点(⼦树),那么他们被称为‘叶⼦节点’这就是⼀些基本的概念⼆叉树的遍历⼆叉树常⽤的遍历⽅式有:前序遍历、中序遍历、后序遍历、层序遍历四种遍历⽅式,不同的遍历算法,其思想略有不同,我们来看⼀下这四种遍历⽅法主要的算法思想:1、先序遍历⼆叉树顺序:根节点 –> 左⼦树 –> 右⼦树,即先访问根节点,然后是左⼦树,最后是右⼦树。

上图中⼆叉树的前序遍历结果为:0 -> 1 -> 3 -> 4 -> 2 -> 5 -> 62、中序遍历⼆叉树顺序:左⼦树 –> 根节点 –> 右⼦树,即先访问左⼦树,然后是根节点,最后是右⼦树。

上图中⼆叉树的中序遍历结果为:3 -> 1 -> 4 -> 0 -> 5 -> 2 -> 63、后续遍历⼆叉树顺序:左⼦树 –> 右⼦树 –> 根节点,即先访问左⼦树,然后是右⼦树,最后是根节点。

上图中⼆叉树的后序遍历结果为:3 -> 4 -> 1 -> 5 -> 6 -> 2 -> 04、层序遍历⼆叉树顺序:从最顶层的节点开始,从左往右依次遍历,之后转到第⼆层,继续从左往右遍历,持续循环,直到所有节点都遍历完成上图中⼆叉树的层序遍历结果为:0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6下⾯是四种算法的伪代码:前序遍历:preOrderParse(int n) {if(tree[n] == NULL)return ; // 如果这个节点不存在,那么结束cout << tree[n].w ; // 输出当前节点内容preOrderParse(tree[n].leftChild); // 递归输出左⼦树preOrderParse(tree[n].rightChild); // 递归输出右⼦树}中序遍历inOrderParse(int n) {if(tree[n] == NULL)return ; // 如果这个节点不存在,那么结束inOrderParse(tree[n].leftChild); // 递归输出左⼦树cout << tree[n].w ; // 输出当前节点内容inOrderParse(tree[n].rightChild); // 递归输出右⼦树}pastOrderParse(int n) {if(tree[n] == NULL)return ; // 如果这个节点不存在,那么结束pastOrderParse(tree[n].leftChild); // 递归输出左⼦树pastOrderParse(tree[n].rightChild); // 递归输出右⼦树cout << tree[n].w ; // 输出当前节点内容}可以看到前三种遍历都是直接通过递归来完成,⽤递归遍历⼆叉树简答⽅便⽽且好理解,接下来层序遍历就需要动点脑筋了,我们如何将⼆叉树⼀层⼀层的遍历输出?其实在这⾥我们要借助⼀种数据结构来完成:队列。

数据结构课后习题及解析第六章

数据结构课后习题及解析第六章

第六章习题1.试分别画出具有3个结点的树和3个结点的二叉树的所有不同形态。

2.对题1所得各种形态的二叉树,分别写出前序、中序和后序遍历的序列。

3.已知一棵度为k的树中有n1个度为1的结点,n2个度为2的结点,……,n k个度为k的结点,则该树中有多少个叶子结点并证明之。

4.假设一棵二叉树的先序序列为EBADCFHGIKJ,中序序列为ABCDEFGHIJK,请画出该二叉树。

5.已知二叉树有50个叶子结点,则该二叉树的总结点数至少应有多少个6.给出满足下列条件的所有二叉树:①前序和后序相同②中序和后序相同③前序和后序相同$7.n个结点的K叉树,若用具有k个child域的等长链结点存储树的一个结点,则空的Child域有多少个8.画出与下列已知序列对应的树T:树的先根次序访问序列为GFKDAIEBCHJ;树的后根次序访问序列为DIAEKFCJHBG。

9.假设用于通讯的电文仅由8个字母组成,字母在电文中出现的频率分别为:,,,,,,,请为这8个字母设计哈夫曼编码。

10.已知二叉树采用二叉链表存放,要求返回二叉树T的后序序列中的第一个结点指针,是否可不用递归且不用栈来完成请简述原因.11. 画出和下列树对应的二叉树:!12.已知二叉树按照二叉链表方式存储,编写算法,计算二叉树中叶子结点的数目。

13.编写递归算法:对于二叉树中每一个元素值为x的结点,删去以它为根的子树,并释放相应的空间。

14.分别写函数完成:在先序线索二叉树T中,查找给定结点*p在先序序列中的后继。

在后序线索二叉树T中,查找给定结点*p在后序序列中的前驱。

15.分别写出算法,实现在中序线索二叉树中查找给定结点*p在中序序列中的前驱与后继。

16.编写算法,对一棵以孩子-兄弟链表表示的树统计其叶子的个数。

17.对以孩子-兄弟链表表示的树编写计算树的深度的算法。

18.已知二叉树按照二叉链表方式存储,利用栈的基本操作写出后序遍历非递归的算法。

19.设二叉树按二叉链表存放,写算法判别一棵二叉树是否是一棵正则二叉树。

二叉树的先序遍历和中序遍历的非递归算法

二叉树的先序遍历和中序遍历的非递归算法
第 2 3卷
第 1期
电 脑 开 发 与 应 用
文 章编 号 :0 35 5 ( 00 9—0 30 1 0—8 0 2 1 ) 10 5 —3
二 叉树 的先 序 遍 历 和 中序 遍 历 的非 递 归 算 法
Di c s i n a s u s o nd Ana y i n— e u s v g r t m o e r r l s s of No r c r i e Al o ih f r Pr o de
t e S p e r rt a e s la t i r e’ r o de r v r a nd ob an non r c sv l ort o i ar r e’ e r ertav r a i t c A tls obt i ng non e ur i e a g ihm f r b n y t e Spr o d r e s lusng s a k. a t. ani
ta e s . r v r a1 The i p t c s an yssng oft e lf r bi r r e’ S pr or r tav r a d bi r r e’ S i r rt a er a . m oran e i al i i he r a o na y t e e de r e s lan na y t e no de r v s 1 K EYW O RDS bi r t e na y r e’ S pr or e t a r a , bi r t e e d r r ve s l na y r e’ a g ihm l ort
Pr o d ( 一 r hid); e r er bt> c l
从二 叉树 先 序遍 历非 递归 算法 实现 时 系统栈 的变 化情 况 , 我们 不难 看 出 , 二叉 树 先序遍 历 实 际上 是走 丫

二叉树的遍历及例题

二叉树的遍历及例题

⼆叉树的遍历及例题⼆叉树的遍历及例题前序遍历就是根在前,中序是根在根在中,前序遍历根 --> 左 --> 右中序遍历左 --> 根 --> 右后序遍历左 --> 右 --> 根如图是⼀颗⼆叉树前序(根左右),中序(左根右),后序(左右根)它的前序遍历结果为: A B D F G H I E C 代表的含义为A( B ( D ( F ,G( H ,I ) ) ,E ) , C )所以第⼀个点⼀定是根节点它的中序遍历结果为: F D H G I B E A C它代表的含义,A(已知它不是叶⼦节点)在中间说明A的左边是左⼉⼦,A的右边是他的右⼉⼦它的后序遍历结果为:F H I G D E B C A解题:如果有前序和中序或者中序和后序可以得到⼆叉树,从⽽得到后序。

如果有前序和后序⽆法的得到⼆叉树。

1.已知前序、中序遍历求后序遍历例:前序遍历:A B G D E C F H中序遍历:G B E D A F C H构建⼆叉树的步骤:1.根据前序遍历特点,得到根节点A2.观察中序遍历结果:根节点左边节点为G B E D,根节点的右边节点为 F C H。

同时,两段也是左右⼦树的中序遍历的结果。

B G D E也是左⼦树前序遍历的结果。

C F H也是右⼦树前序遍历的结果。

3.重复 1 2的步骤,直到找到叶⼦结点就可以得到最后的⼆叉树。

例题:题意:给出中序遍历和前序遍历,让你找到后序遍历的结果。

#include <iostream>using namespace std;const int maxn = 105;int pre[maxn],in[maxn],pos[maxn];int infind(int root,int l,int r){//在中序遍历中找到当前根节点的位置for(int i=l;i<r;i++){if(in[i]==root){return i;}}}int cnt;void posorder(int prel,int prer,int inl,int inr){if(prel==prer) return ;int root=infind(pre[prel],inl,inr);//找当前的根的位置int len=root-inl;posorder(prel+1,prel+1+len,inl,inl+len);//prel的位置是root的位置,删去posorder(prel+1+len,prer,inl+1+len,inr);//inl+len+1的位置是root的位置,删去//进⾏完左边和右边的遍历之后,进⾏赋值。

二叉树中以广义表-(先序-中序后序)递归-中序非递归输出

二叉树中以广义表-(先序-中序后序)递归-中序非递归输出

#include<stdio.h>#include<stdlib.h>#define STACK_INIT_SIZE 100#define STACKINCREMENT 10#define OVERFLOW -2#define OK 1#define ERROR -1#define TRUE 1#define FALSE 0typedef char TElemType;typedef int Status;typedef struct BiTNode{ // 二叉链表储存结构TElemType data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;Status CreateBiTree<BiTree &T>{//先序序列建立二叉树char ch;scanf<"%c",&ch>;if<ch=='#'> T=NULL;else{if<!<T=<BiTNode*>malloc<sizeof<BiTNode>>>> return<OVERFLOW>;T->data=ch;CreateBiTree<T->lchild>;CreateBiTree<T->rchild>;}return OK;}void PrintBiTree<BiTree &T>{ //以广义表的形式输出if<T!= NULL>{printf<"%c", T->data>;if<T->lchild != NULL || T->rchild!=NULL>{printf<"<">;PrintBiTree<T->lchild>;if<T->rchild != NULL>{printf<",">;}PrintBiTree<T->rchild>;printf<">">;}}}Status PrintElement<TElemType e>{// 访问函数printf<"%c",e>;return OK;}Status PreOrderTraverse<BiTree T,Status<*Visit><TElemType e>>{//先序遍历二叉树的递归算法if<T>{if<Visit<T->data>>// printf<"<">;if<PreOrderTraverse<T->lchild,Visit>>// printf<",">;if<PreOrderTraverse<T->rchild,Visit>>// printf<">">;return OK;return ERROR;}elsereturn OK;}Status InOrderTraverse<BiTree T, Status<*Visit><TElemType>> {//中序遍历二叉树的递归算法if <T> {if <InOrderTraverse<T->lchild, Visit>>if <Visit<T->data>>if <InOrderTraverse<T->rchild, Visit>>return OK;return ERROR;}elsereturn OK;}Status PostOrderTraverse<BiTree T, Status<*Visit><TElemType>> {//后序遍历二叉树的递归算法if <T> {if <PostOrderTraverse<T->lchild, Visit>>if <PostOrderTraverse<T->rchild, Visit>>if <Visit<T->data>>return OK;return ERROR;}elsereturn OK;}//中序遍历二叉树的非递归算法typedef struct { // 栈存储结构与操作BiTree *base;BiTree *top;int stacksize;}Stack;Status InitStack<Stack &S> { //构造空栈S.base = <BiTree*>malloc<STACK_INIT_SIZE * sizeof<BiTree>>;if <!S.base> exit<OVERFLOW>;S.top = S.base;S.stacksize = STACK_INIT_SIZE;return OK;}Status GetTop<Stack S, BiTree &e>{ //读栈顶元素if <S.top == S.base> return ERROR;e = *<S.top - 1>; return OK;}Status Push<Stack &S, BiTree e>{ //入栈if <S.top - S.base >= S.stacksize> {S.base = <BiTree*>realloc<S.base, <S.stacksize + STACKINCREMENT> * sizeof<BiTree>>;if <!S.base> exit<OVERFLOW>;S.top = S.base + S.stacksize;S.stacksize += STACKINCREMENT;}*S.top++ = e;return OK;}Status Pop<Stack &S, BiTree &e>{ //出栈if <S.top == S.base> return ERROR;e = *--S.top;return OK;}Status StackEmpty<Stack S>{ //判栈空if <S.base == S.top> return TRUE;else return FALSE;}Status InOrderTraverse2<BiTree T, Status <*Visit><TElemType>> { //中序遍历二叉树的非递归算法Stack S;BiTree p;InitStack<S>;Push<S, T>;while <!StackEmpty<S>> {while <GetTop<S, p> && p> Push<S, p->lchild>;Pop<S, p>;if <!StackEmpty<S>> {Pop<S, p>;if <!Visit<p->data>> return ERROR;Push<S, p->rchild>;}}return OK;}int main<>{BiTree T;printf<"请输入二叉树先序序列:">;CreateBiTree<T>;printf<"\n">;printf<"以广义表的形式输出:">;PrintBiTree<T>;printf<"\n\n">;printf<"先序递归遍历顺序:">;PreOrderTraverse<T, PrintElement>;printf<"\n">;printf<"中序递归遍历顺序:">;InOrderTraverse<T, PrintElement>;printf<"\n">;printf<"后序递归遍历顺序:">;PostOrderTraverse<T, PrintElement>;printf<"\n\n">;printf<"中序非递归遍历顺序:">;InOrderTraverse2<T, PrintElement>;printf<"\n">;return 0;}。

先序中序后序遍历二叉树例题

先序中序后序遍历二叉树例题

先序中序后序遍历二叉树例题二叉树的先序、中序和后序遍历是树的三种常见遍历方式。

假设我们有以下二叉树作为例题:
A.
/ \。

B C.
/ \ \。

D E F.
1. 先序遍历(Preorder Traversal),先访问根节点,然后递归地先序遍历左子树,最后递归地先序遍历右子树。

遍历顺序为根-左-右。

对于上述例题,先序遍历的结果为,A, B, D, E, C, F。

2. 中序遍历(Inorder Traversal),先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树。

遍历顺序为左-根-右。

对于上述例题,中序遍历的结果为,D, B, E, A, C, F。

3. 后序遍历(Postorder Traversal),先递归地后序遍历左子树,然后递归地后序遍历右子树,最后访问根节点。

遍历顺序为左-右-根。

对于上述例题,后序遍历的结果为,D, E, B, F, C, A。

需要注意的是,先序、中序和后序遍历的结果都是唯一的,即给定一棵二叉树,它们的遍历结果是确定的。

希望以上例题能够帮助你理解二叉树的先序、中序和后序遍历方式。

如果还有其他问题,请继续提问。

中序遍历代码

中序遍历代码

中序遍历代码中序遍历是二叉树的一种遍历方式,它按照“左子树-根节点-右子树”的顺序访问二叉树的所有节点。

在编写中序遍历代码时,我们可以使用递归或迭代的方式来实现。

递归实现中序遍历递归是一种简洁而直观的方法来实现中序遍历。

下面是递归实现中序遍历的代码:class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = rightdef inorderTraversal(root):if root is None:return []result = []result.extend(inorderTraversal(root.left))result.append(root.val)result.extend(inorderTraversal(root.right))return result在这段代码中,我们定义了一个TreeNode类来表示二叉树的节点。

每个节点包含一个值val、左子节点left和右子节点right。

函数inorderTraversal()接受一个二叉树的根节点作为参数,并返回一个列表,其中包含了按照中序遍历顺序访问得到的所有节点值。

该函数首先进行终止条件判断:如果当前节点为空,则直接返回空列表。

否则,我们先通过递归调用处理左子树,将结果添加到结果列表中。

然后将当前节点的值添加到结果列表中。

最后,再通过递归调用处理右子树,并将结果添加到结果列表中。

最终返回结果列表。

迭代实现中序遍历除了使用递归,我们还可以使用迭代的方式来实现中序遍历。

迭代方式通常借助栈来辅助实现。

下面是迭代实现中序遍历的代码:def inorderTraversal(root):if root is None:return []result = []stack = []node = rootwhile node or stack:while node:stack.append(node)node = node.leftnode = stack.pop()result.append(node.val)node = node.rightreturn result在这段代码中,我们同样定义了一个TreeNode类来表示二叉树的节点。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档