c++ 数据结构——二叉树的构建及其应用,实现左右子树交换并输出前序递归结果

数据结构实习——二叉树及其应用

一、实习题目及要求

1、题目:
二叉树基本算法的实现
2、功能要求:
(1)键盘输入二叉树结点前序序列,创建一棵二叉树;
(2)实现SwapTree方法,以根结点为参数,交换每个结点的左子树和右子树(提示:前序递归);
(3)实现Find方法,查找值为key的结点,并输出该结点的所有祖先结点。
3、创建要求:
(1)要求键盘输入二叉树前序序列(程序5.12)
(2)空结点以#表示
4、可选方法:
(1)对BinaryTree模板进行功能扩充
(2)自己定义并实现二叉树类
在这里插入图片描述

二、问题描述

本题要求我们实现二叉树的基本算法,并进行相应的功能补充,由数据结构中二叉树的定义可知,二叉树的结点由一个数据元素和分别指向其左、右子树的两个分支构成,所以在本程序二叉树的构造是采用二叉链表的链式存储结构,链表中的结点应包含三个域:数据域和左、右孩子的指针域。这种存储结构可以方便二叉树的建立以及遍历。输入二叉树的先序序列字符,建立二叉链表。

三、问题分析

本题我选用的方法是对BinaryTree模板进行功能扩充,根据题意,我们需要增加两个功能函数;首先第一个函数是要实现左右子树的交换,题目中提示我们可以运用前序递归,这里我们就可以运用值传递的原理来进行左右指数的交换;第二的函数要求我们实现Find的方法,(这里我额外编写了函数FindAncestor来完成相关功能)查找值为key的结点,并输出该结点的所有祖先结点,所以我们不光要实现key结点的查找,还要运用parent函数把所有的祖先节点全部输出。

四、设计思想

本题要求我们实现键盘输入二叉树结点前序序列,创建一棵二叉树,然后交换每个结点的左子树和右子树,并输出,再查找值为key的结点,并打印该结点的所有祖先结点。为实现上述功能,需要解决的关键问题是二叉树建立过程、二叉树左右子树的交换、查找值等于key的结点过程和存储查找结点的所有祖先结点过程。基本可以归结为以下三点:
1.建立二叉树时,按照完全二叉树的结点顺序输入,#表示空结点。 若不是空结点时,则建立一个新结点,并且将其作为左孩子或右孩子结点连接到它的父结点上(第一个结点无父结点);若是空结点,则将空结点(NULL)作为左孩子或右孩子结点连接到它的父节点上;
2.为实现二叉树左右子树的交换,则需要利用前序递归,原理同值传递的原理相同,设置中间指针变量med,然后再进行交换操作;
3.为实现输出所有祖先节点,则需要利用递归前序遍历算法遍历二叉树,在遍历过程中,将遍历的根结点的关键字与所给查找关键字key比较,相等时结束遍历;不等时继续遍历查找直至找到等于所给查找关键字的根结点或遍历完整棵二叉树;在遍历过程中,需将访问过的结点存入栈中,并同时访问该结点的左孩子结点,若左孩子结点是待查找结点,则栈中结点即是左孩子结点的所有祖先结点,然后依次出栈输出信息。

五、调试报告

【调试一】
起初,我编写了SwapTree函数,在测试过程中我发现,输出的前序序列结果并不正确(如图①所示),经过调试,我发现,在运行时,并没有实际调用SwapTree函数,原来是因为我并没有把二叉树的根节点传入SwapTree函数,导致直接输出了所输入的前序序列。
于是,为方便传入根节点,也方便在主函数中的调用,这里我效仿BinaryTree头文件中对于Find、Parent等函数的方式在编写了公有函数SwapTree,即BinTreeNode * SwapTree(){return SwapTree(root);},在这个函数中把根节点传入,即可正常运行并输出正确的交换后的前序序列。
在这里插入图片描述
图①

【调试二】
在测试过程中出现如图②所示的错误,经过调试发现结点指针a我把它初始化给了根节点,所以造成如下错误。此外在修改代码的过程我发现我的Find函数也出现了问题,于是我在原Find函数的基础上进行了如下更改:

bool Find(T &x, BinTreeNode<T> * &a){
   return Find(root, x, a);}
template<typename T>bool BinaryTree<T>::Find(BinTreeNode<T> *subTree, T &x, BinTreeNode<T>* &a)const{
   //在子树中寻找数据为x的结点
	if (!subTree){
   
		return false;
	}
	if (subTree->data == x){
   
		a = subTree;
		return 
### 回答1: 可以使用栈来实现二叉树左右子树交换。具体步骤如下: 1. 将根节点入栈。 2. 循环执行以下操作,直到栈为空: a. 弹出栈顶节点,交换左右子树。 b. 如果该节点有左子树,则将左子树入栈。 c. 如果该节点有右子树,则将右子树入栈。 3. 对交换后的二叉树进行后序遍历,输出遍历结果。 代码实现如下: ```python def invertTree(root): if not root: return None stack = [root] while stack: node = stack.pop() node.left, node.right = node.right, node.left if node.left: stack.append(node.left) if node.right: stack.append(node.right) res = [] def postorder(node): if not node: return postorder(node.left) postorder(node.right) res.append(node.val) postorder(root) return res ``` 其中,invertTree函数用于实现二叉树左右子树交换,并返回后序遍历结果。postorder函数用于实现后序遍历,将遍历结果存储在res列表中。 ### 回答2: 二叉树左右子树交换可以使用递归或非递归的方式实现,本篇回答主要介绍一种使用非递归方式实现二叉树左右子树交换输出后序遍历结果的方法。 首先,需要使用栈来实现递归遍历二叉树。具体地,将根节点入栈,然后重复以下步骤: 1. 弹出栈顶节点,访问该节点; 2. 将该节点的左右子节点(如果有)分别入栈; 3. 继续重复步骤1-2,直到栈为空。 在每次遍历时,交换当前节点的左右子树即可。 代码实现如下: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def postorderTraversal(root): if not root: return [] stack = [root] result = [] while stack: node = stack.pop() if node.left: stack.append(node.left) if node.right: stack.append(node.right) node.left, node.right = node.right, node.left # 交换子树 result.append(node.val) result.reverse() # 后序遍历,需要翻转结果 return result ``` 以上代码实现了非递归遍历二叉树交换左右子树的过程,并输出后序遍历结果。值得注意的是,在交换节点的左右子树时,需要使用如下语法: ```python node.left, node.right = node.right, node.left ``` 这是Python中非常方便的一种交换变量值的写法。如果使用其他语言,可能需要额外定义一个临时变量来实现交换操作。 总结:使用栈来实现递归遍历二叉树可以方便地控制遍历的顺序,进而实现对节点的操作。在本题中,通过交换左右子树实现了树的左右翻转,并最终输出后序遍历结果。该题目不难,但可以锻炼对树的遍历和操作,对于加深对二叉树的理解有一定帮助。 ### 回答3: 对于这个问题,我们可以使用非递归的方式进行二叉树左右子树交换。具体实现如下: 首先,我们需要定义一个辅助栈,用来存储节点。 然后,我们从根节点开始,将其入栈。 接着,我们开始遍历栈,当栈不为空时,取出栈顶元素,并交换左右子树。 然后,我们再将其左右子树分别入栈,先入右子树,后入左子树,这样就能保证后序遍历的顺序。 最后,我们再遍历一遍交换后的二叉树输出后序遍历结果即可。 代码实现如下所示: ```python def swapSubTree(root): if not root: return stack = [root] while stack: node = stack.pop() node.left, node.right = node.right, node.left if node.left: stack.append(node.left) if node.right: stack.append(node.right) res = [] def postorder(root): if not root: return postorder(root.left) postorder(root.right) res.append(root.val) postorder(root) return res ``` 整个算法的时间复杂度为$O(n)$,其中$n$为二叉树的节点个数。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值