非递归中序遍历二叉树的应用

今天在准备武汉理工考研复试的时候看到这么一道题,使用非递归函数计算二叉树的单节点个数。 由于有很长一段时间没有写有关树的编程了,去网上搜了下信息结合自己之前的笔记,完成了这道题。 学习篇(2)

首先,回忆如何建立二叉树。建立二叉树是使用递归的方法,由于在键盘上输入并不方便。将待输入的放在txt中更好,只不过格式必须没错,不然会触发异常。输入格式例子 1 2 4 # # 5 # # 3 4 # # #
把它存在txt文件中,名字为data.txt。想改成什么就改成什么,不必每次调试都输入
建立出的二叉树应该是这个样子
在这里插入图片描述

由于我对画图软件确实不熟悉,想好好模拟下这个流程,但是太费时间- -

#include "pch.h"
#include <iostream>
#include <fstream>
#include <stack>

using namespace std;

ifstream input;
typedef struct TreeNode
{
 char data;
 struct TreeNode *lchild;
 struct TreeNode *rchild;
}TreeNode;

TreeNode* CreateTreeNode() //这个创建树的代码不难,遇到#就代表空节点
{
 TreeNode *p;
 char tmp;
 input >> tmp;  //文件流向后读取一个字符,空格忽略
 if (tmp == '#')
 {
  p = NULL;
 }
 else
 {
  p = new TreeNode;
  p->data = tmp;
  p->lchild = CreateTreeNode();
  p->rchild = CreateTreeNode();
 }
 return p;
}

void InOrderTraverse(TreeNode *T) //先回忆下中序递归遍历
{
 if (T != NULL)
 {
  InOrderTraverse(T->lchild);
  cout << T->data<<' ';
  InOrderTraverse(T->rchild);
 }
}
void InOrderTravel(TreeNode *Tree) //回忆下非递归中序遍历二叉树
{
 TreeNode *T = Tree;
 stack<TreeNode> st; //非递归遍历的话就必须得存储从根节点走下来得路径,用栈来模拟
 while (T || !st.empty())  //T代表得是当前得节点
 {
  while (T)  //当前节点不空 就一直向左走且存到栈,记录走下来的位置
  {
   st.push(*T);
   T = T->lchild;
  }
  if (!st.empty()) //到这里说明左边空了,此时如果栈中有节点,也就可以弹出来,访问它了 
  {
   T = &st.top();  //注意T是指针
   st.pop();
   cout << T->data << ' ';
   T = T->rchild;  //T访问完了,此时可以进入它的右分支了 重复以上操作
  //这段代码需要好好理解  最好画图 自己走一遍过程,然后就可以懂了。但是不一定会写,所以要练习
  }
 }
}
int MyFunc(TreeNode *Tree) //非递归中序遍历计算单节点个数,这个就直接应用非递归中序遍历了
{
 int count = 0;
 TreeNode *T = Tree;
 stack<TreeNode> st;
 while (T || !st.empty())
 {
  while (T)
  {
   st.push(*T);
   T = T->lchild;
  }
  if (!st.empty())
  {
   T = &st.top();
   st.pop();
   if (T->lchild == NULL && T->rchild != NULL) count++; //可以把这俩行代码看作遍历时需要对节点的操作,
   else if (T->rchild == NULL && T->lchild != NULL) count++;
   T = T->rchild;
  }
 }
 return count;
} //这种非递归遍历 可以解决二叉树中的许多问题,考试还是很有用的。初试也考过
int main()
{
 input.open("F:\\AlgorithmPRJ\\树编程\\data.txt"); //这就是存放待输入文件txt的路径
 if (!input.is_open()) return -1;
 TreeNode *T = CreateTreeNode(); //建树
 cout << "中序遍历..." << endl;
 InOrderTraverse(T);
 cout << endl;
 cout << "非递归中序遍历.." << endl;
 InOrderTravel(T);
 cout << endl;
 cout << "非递归遍历二叉树得二叉树单节点个数为" << MyFunc(T) << endl;
 return 0;
 }

小结下吧:其实树的编程说复杂也复杂,看代码想的头疼,说简单也简单。主要是画一下图 多走几遍流程就懂了。然而算法看的懂不代表会写,多多练习 受益匪浅。

PS:树编程真的很抽象,我的理解方式是把所有的结点都看作一样的东西,它们本身也就是一样的,由于计算机不知道树的形状,给它编程,它必将遇到空节点的情况,这里空节点就是一种出口,把空节点看作一颗节点的话,它的父节点的‘左子树’就访问完了,可以访问父节点了。紧接着 进入父节点的右子树,开始再次重复之前的操作,因为此时右子树和 最大的那棵树 性质上一样…每个人的理解方式不一样,我希望有帮助。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值