二叉搜索树 后序遍历递归和非递归(c程序干货满满)

后序遍历是 左右根 是遍历里面最复杂的 

后续遍历 两种方法

1.递归

void print4(struct node*root)
{
	if(root!=NULL)
	{
		print4(root->left);   //传 当前节点的左节点   (左)
		print4(root->right);  //传 当前节点的右节点    (右)
		printf("%d\t",root->data);//打印 节点        (根)
	}
}

 

递归

     分析:

假设遍历如图的二叉树

 在非递归里面 中序和后续有相同的地方  先来分析分析 中序遍历 和后序遍历的结果

中序: 30--40--45--........

后续: 30--45--40--........

如果我们按照 中序遍历的思路来  

 

 可以见的 当pnode到45这个节点在出栈就是 a[i](a[0]=50)

为了避免它这次出栈到 50 这个节点 所有我们在中间在 入栈 也就是说 后序遍历入栈多次

那遍历的结果就是:30--40--45--40.....

但是我后序遍历是:30--45--40......

只要我们想办法把这个40给(‘删除’)的话那遍历的结果就对了

我们在回过来仔细想想  后序打印 先是3045  他们有一个共同点 就是没有子节点  而40 是把30 45 都打印 了才 打印 只要我们在遍历30 和 45 的时候他们一个标记 当标记存在的时候就可以打印

 没有标记不打印   这样30--  40 --45--40......前面的40就打印不出来了

代码实现

//后续遍历 非递归
void print5(struct node*root)
{
	struct node*a[20];  //结构体数组 
	struct node*pnode=root;
	struct node*x=NULL;  //标记 
	int i=-1;
	while(pnode)
	{
		a[++i]=pnode;  //入栈 
		pnode=pnode->left;  
	}
	while(i!=-1)//无路可走的时候 
	{
		pnode=a[i--]; //出栈 
		if(pnode->right==NULL || pnode->right==x)  //当右边为空 或者 被标记 
		{
			printf("%d\t",pnode->data);
			x=pnode;  //给节点标记 
		}
		else
		{
			a[++i]=pnode;  //入栈 
			pnode=pnode->right;
			while(pnode)
			{
				a[++i]=pnode;//入栈 
				pnode=pnode->left;
			}
		}
	}
 } 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
### 回答1: 中序遍历的递归算法: 1. 如果为空,则返回。 2. 对根节点的左子进行中序遍历。 3. 访问根节点。 4. 对根节点的右子进行中序遍历。 中序遍历的非递归算法: 1. 初始化一个栈,将根节点入栈。 2. 如果栈不为空,执行以下操作: a. 将栈顶节点弹出并访问。 b. 如果栈顶节点的右子不为空,将右子入栈。 c. 如果栈顶节点的左子不为空,将左子入栈。 后序遍历递归算法: 1. 如果为空,则返回。 2. 对根节点的左子进行后序遍历。 3. 对根节点的右子进行后序遍历。 4. 访问根节点。 后序遍历非递归算法: 1. 初始化两个栈,将根节点入栈1。 2. 如果栈1不为空,执行以下操作: a. 将栈1顶部节点弹出并压入栈2。 b. 如果栈1顶部节点的左子不为空,将左子入栈1。 c. 如果栈1顶部节点的右子不为空,将右子入栈1。 3. 当栈1为空时,依次弹出栈2中的节点并访问。 ### 回答2: 二叉是一种常见的数据结构,在计算机科学中应用广泛。在对二叉进行遍历时,有三种方式:前序遍历(先遍历根节点,然后遍历左子和右子)、中序遍历(先遍历左子,然后遍历根节点和右子)和后序遍历(先遍历左子和右子,然后遍历根节点)。对于一棵二叉,它们的遍历序列各不相同,因此在编写程序时需要对它们进行分类讨论。 1. 中序遍历的递归算法 中序遍历的递归算法相对简单,只需按照左子-根节点-右子的顺序遍历即可。具体实现如下: ``` void inorderTraversal(TreeNode* root) { if (root == nullptr) return; inorderTraversal(root->left); // 处理根节点 cout << root->val << " "; inorderTraversal(root->right); } ``` 2. 中序遍历的非递归算法 采用非递归算法实现中序遍历时,需要借助栈来记录遍历过程中的节点信息。具体实现如下: ``` void inorderTraversal(TreeNode* root) { stack<TreeNode*> stk; while (root != nullptr || !stk.empty()) { while (root != nullptr) { stk.push(root); root = root->left; } root = stk.top(); stk.pop(); // 处理根节点 cout << root->val << " "; root = root->right; } } ``` 3. 后序遍历递归算法 后序遍历递归算法也相对简单,只需按照左子-右子-根节点的顺序遍历即可。具体实现如下: ``` void postorderTraversal(TreeNode* root) { if (root == nullptr) return; postorderTraversal(root->left); postorderTraversal(root->right); // 处理根节点 cout << root->val << " "; } ``` 4. 后序遍历非递归算法 采用非递归算法实现后序遍历时,需要借助栈来记录遍历过程中的节点信息。具体实现如下: ``` void postorderTraversal(TreeNode* root) { stack<TreeNode*> stk; TreeNode* prev = nullptr; while (root != nullptr || !stk.empty()) { while (root != nullptr) { stk.push(root); root = root->left; } root = stk.top(); if (root->right == nullptr || root->right == prev) { stk.pop(); // 处理根节点 cout << root->val << " "; prev = root; root = nullptr; } else { root = root->right; } } } ``` 在以上算法中,递归算法较为简单易懂,但当二叉较大时,容易造成栈溢出;非递归算法节省了栈空间,但代码相对复杂。在实际应用中,应根据具体情况选择合适的算法。 ### 回答3: 二叉是一种数据结构,由一个根节点和每个节点最多有两个子节点组成。二叉的遍历是指按照某种次序依次访问二叉中的所有节点。其中,中序遍历是指先访问左子,再访问根节点,最后访问右子后序遍历是指先访问左子,再访问右子,最后访问根节点。 在编写程序实现二叉的中序遍历和后序遍历时,可采用递归非递归算法两种方法进行。 递归算法: 中序遍历的递归算法 1. 如果根节点为NULL,返回 2. 中序遍历根节点的左子 3. 访问根节点 4. 中序遍历根节点的右子 代码如下: ``` void inorderTraversal(TreeNode* root) { if(root == NULL) return; inorderTraversal(root->left); cout<<root->val<<" "; inorderTraversal(root->right); } ``` 后序遍历递归算法 1. 如果根节点为NULL,返回 2. 后序遍历根节点的左子 3. 后序遍历根节点的右子 4. 访问根节点 代码如下: ``` void postorderTraversal(TreeNode* root) { if(root == NULL) return; postorderTraversal(root->left); postorderTraversal(root->right); cout<<root->val<<" "; } ``` 非递归算法: 中序遍历的非递归算法 1. 将根节点入栈 2. 当栈不为空时,弹出栈顶元素 3. 如果弹出的元素不为空,将其右子节点入栈 4. 如果弹出的元素为空,继续弹出栈顶元素并访问 5. 如果弹出的元素不为空,将其左子节点入栈 代码如下: ``` vector<int> inorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode*> stk; while(root || !stk.empty()) { while(root) { stk.push(root); root = root->left; } root = stk.top(); stk.pop(); res.push_back(root->val); root = root->right; } return res; } ``` 后序遍历非递归算法 1. 将根节点入栈 2. 当栈不为空时,弹出栈顶元素 3. 将弹出的元素加入结果列表 4. 如果弹出的元素左子节点不为空,将其左子节点入栈 5. 如果弹出的元素右子节点不为空,将其右子节点入栈 6. 将结果列表反,得到后序遍历结果 代码如下: ``` vector<int> postorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode*> stk; while(root || !stk.empty()) { while(root) { stk.push(root); res.insert(res.begin(), root->val); root = root->right; } root = stk.top(); stk.pop(); root = root->left; } return res; } ``` 以上就是关于二叉中序遍历和后序遍历递归非递归算法的详细介绍。在编写程序时,需要注意遍历时的访问顺序以及栈的使用。通过使用不同的算法,可以达到不同的时间和空间复杂度,因此需要根据具体问题场景进行选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiexiexiexieqing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值