要求:以左右孩子表示法实现链式方式存储的二叉树(lson—rson),以菜单方式设计并完成功能任务:建立并存储树、输出前序遍历结果、输出中序遍历结果、输出后序遍历结果、交换左右子树、统计高度,其中对于中序、后序的遍历运算要求采用非递归的方式实现。

写在前面

二叉树向量存储的优势和弊端

  二叉树同样有两种存储方式,数组和链式存储,对于数组来说,我们利用二叉树的性质然后利用下标可以方便的找到一个节点的子节点和父节点。

    

  

二叉树的性质:
  1.二叉树的第i层上至多有2i-1个节点
  2.深度为K的二叉树至多有2k-1个节点
  3.任何一个二叉树中度数为2的节点的个数必度数为0的节点数目少1.
    说明:度数为0,为叶子节点。
  4.具有n个节点的完全二叉树的深度为|_Log2N_|+1
  5.若完全二叉树中的某节点编号为i,则若有左孩子编号为2i,若有右孩子编号为2i+1,母亲节点为i/2。

  结合第5条性质:

    若完全二叉树中的某节点编号为i,则若有左孩子编号为2i,若有右孩子编号为2i+1,母亲节点为i/2。

  可以在这种完全二叉树中十分方便的找到任何相关联(父子、兄弟等)的元素。

  但是由于顺序存储天生适配于完全二叉树,对于下面这种非完全二叉树并不合适,主要体现在空间上的浪费,所以我们需要用到另一种存储方式——链式存储。

   

 

二叉树的链表存储

  在链式存储中,每个节点的结构如下

  

结构描述:

  一个存储数据的变量与两个指向孩子的指针域。

  利用指针域我们便可以完美的存储非完全二叉树,如下:

   

代码分解:

1.定义结构体变量,其中的tag只会在后序遍历(非递归)过程中使用。

typedef struct node{int tag;    //在后序遍历过程中来标志一个结点是第一次访问(tag=0)还是第二次访问(tag=1)int data;struct node* lson;struct node* rson;
}Bitree;
typedef Bitree* Bitpo;

2.创建二叉树。创建二叉树的方式有3种(前序、中序、后序),其过程与二叉树的遍历类似,这里我用前序来创建二叉树。

void create(Bitpo &T){                    //创建并存储二叉树,以先序顺序输入并存储(递归)int x;cin>>x;if(x==0)                              //'0'表示空节点T=NULL;else{T=(Bitpo)malloc(Len);T->data=x;create(T->lson);create(T->rson);}
}

3.前序遍历二叉树(递归)。

void pretraversal(Bitpo T){              //先序遍历(递归)if(T){cout<<T->data<<" ";pretraversal(T->lson);pretraversal(T->rson);}
}

4.中序遍历二叉树(非递归)。这里用数组模拟栈,用一个整型变量模拟栈顶指针,需要回溯。

void intraversal(Bitpo T){               //中序遍历(非递归)Bitpo stack[101];                    //定义栈并初始化Bitpo Q=T;int p=0;                             //初始化栈顶指针do{while(Q!=NULL){                  //遍历左子树p++;      if(p==101){cout<<"Error:stack is full!!";return;                  //栈满,返回0                   }stack[p]=Q;                  //入栈,从下标1开始Q=Q->lson;}if(p!=0){Q=stack[p];p--;                         //退栈cout<<Q->data<<" ";          //访问根节点Q=Q->rson;                   //遍历右子树}}while(p!=0||Q!=NULL);
}

5.后序遍历二叉树(非递归)。同样的用数组模拟栈,用一个整型变量模拟栈顶指针,需要回溯和设立标志tag(已在结构体中定义),因为根节点最后一个访问,所以入栈时令tag=0入栈,第一次回溯出栈时令tag=1,重新入栈,第二次回溯出栈时才可以访问。

void posttraversal(Bitpo T){             //后序遍历(非递归)Bitpo stack[101];        //定义栈并初始化int p=0;              //初始化栈顶指针Bitpo Q=T;do{while(Q!=NULL){p++;if(p==101){      //栈满,退出cout<<"Error:stack is full!!";return;}Q->tag=0;        //第一次入栈,tag=0stack[p]=Q;  //入栈Q=Q->lson;}if(p!=0){Q=stack[p];p--;             //退栈if(Q->tag==0){   //第一次访问,令tag=1,重新入栈Q->tag=1;p++;stack[p]=Q;Q=Q->rson;//继续搜索Q的右子树}else{             //第二次入栈,访问Q结点,并且为了回溯,令Q=NULLcout<<Q->data<<" ";Q=NULL;}} }while(p!=0||Q!=NULL);
}

6.交换左右子树(递归)。

void exchange(Bitpo T){                  //交换左右子树(递归)if(T){Bitpo x=T->lson;T->lson=T->rson;T->rson=x;exchange(T->lson);exchange(T->rson);}
}

7.求二叉树的高度(递归)。

int height(Bitpo T){                     //求高度(递归)if(T){return 1+max(height(T->lson),height(T->rson));}elsereturn 0;
}

8.主函数如下。

int main(){int q=1;Bitpo root;while(q){cout<<"1.create and store binary tree!"<<endl;cout<<"2.travel in preorder!"<<endl;cout<<"3.travel in inorder!"<<endl;cout<<"4.travel in postorder!"<<endl;cout<<"5.change lson and rson!"<<endl;cout<<"6.calculate the height of the tree!"<<endl;cout<<"0.exit!"<<endl;cin>>q;switch(q){case 0:q=0;break;case 1:create(root);cout<<endl<<"create successfully!"<<endl<<endl;break; case 2:cout<<"preorder:";pretraversal(root);cout<<endl<<endl;break;case 3:cout<<"inorder:";intraversal(root);cout<<endl<<endl;break;case 4:cout<<"postorder:";posttraversal(root);cout<<endl<<endl;break;case 5:exchange(root);cout<<"exchange successfully!!"<<endl<<endl;break;case 6:cout<<"height:"<<height(root)<<endl<<endl;break;}}return 0;
}

转载于:https://www.cnblogs.com/FrankChen831X/p/10326086.html

二叉树的创建、遍历(递归和非递归实现)、交换左右子数、求高度(c++实现)相关推荐

  1. 二叉树三种遍历方式的非递归实现

    树的递归实现方式很简单,下面介绍三种遍历的非递归实现. 树的遍历有个特点,那就是在处理具体问题时,绝大多数情况下是在当前循环.或函数(或是子树)的根节点来处理的,能够注意到当前根节点是如何从上个根节点 ...

  2. 二叉树几种遍历算法的非递归实现

    二叉树遍历的非递归实现 相对于递归遍历二叉树,非递归遍历显得复杂了许多,但换来的好处是算法的时间效率有了提高.下面对于我学习非递归遍历二叉树算法的过程进行总结 为了便于理解,这里以下图的二叉树为例,分 ...

  3. 二叉树创建及遍历算法(递归及非递归)(转)

    //二叉树处理头文件 //包括二叉树的结构定义,二叉树的创建,遍历算法(递归及非递归), /* 作者:成晓旭 时间:2001年10月7日(18:49:38-20:00:00) 内容:完成二叉树创建,二 ...

  4. 二叉树的递归和非递归遍历

    二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的.对于二叉树,有前序.中序以及后序三种遍历方法.因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易 ...

  5. 转载:二叉树的前中后和层序遍历详细图解(递归和非递归写法)

    二叉树的前中后和层序遍历详细图解(递归和非递归写法) Monster_ii 2018-08-27 17:01:53 50530 收藏 403 分类专栏: 数据结构拾遗 文章标签: 二叉树 前序 中序 ...

  6. 二叉树的链式结构的非递归遍历

    二叉树的链式结构的非递归遍历 一. 非递归前序遍历和非递归中序遍历 1.    Stack.h #ifndef__STACK_H__ #define__STACK_H__ #include<st ...

  7. 二叉树的三种遍历(递归与非递归) + 层次遍历

    <转载于  >>> > 二叉树是一种非常重要的数据结构,很多其他数据机构都是基于二叉树的基础演变过来的.二叉树有前.中.后三种遍历方式,因为树的本身就是用递归定义的,因此 ...

  8. 二叉树的遍历-递归与非递归 - 海子

    二叉树的遍历-递归与非递归 二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的.对于二叉树,有前序.中序以及后序三种遍历方法.因为树的定义本身就是递归定义,因此采用递归的方 ...

  9. 二叉树的先中后序递归和非递归遍历(数据结构作业)

    一.设计思想 我创建二叉树是用的先序创建,其中用'#'代表空节点. 1.递归先序遍历 (1)如果当前节点为空节点(用'#'代表空节点),结束当前函数 (2)打印当前节点 (2)递归当前节点的左子树 ( ...

  10. 二叉树的创建——递归与非递归

    目录 一.知识铺垫 二.二叉树的创建之递归 三.二叉树的创建之非递归(迭代) 初学者对于二叉树的遍历(前序遍历,中序遍历,后序遍历,层序遍历),这些放在最早学习的内容,应该是非常熟悉的,但是渐渐的就会 ...

最新文章

  1. Php的if自动转换类型,php之数据类型自动转换,php之数据类型转换_PHP教程
  2. qlabel可以选中吗_QLabel-标签控件的应用
  3. On the Old, the New —— 用sql语句生成语句的例子
  4. python接口测试类型_python 接口测试字符类型转换
  5. 工业交换机的价格为什么有高低之分?
  6. oracle中or会使索引,为何查询条件中多了 OR 选项,索引就走全扫描?
  7. Laravel 的 Redis 使用指南
  8. 局域网文件共享服务器无法写入,局域网共享文件禁止复制、共享文件只读不能保存法...
  9. 华为ensp配置vrrp
  10. 200+ML知识速查卡;『图解算法数据结构』配套代码;『剑指Offer』解题代码;『Python3』高频面试题目集;前沿论文 | ShowMeAI资讯日报
  11. python 微信支付sdk_weixin-python
  12. (阅读笔记)SecureNN: 3-Party Secure Computation for Neural Network Training
  13. 手持式水质监测仪在污水处理中的应用
  14. JAVA征兵管理系统
  15. 余弦定理对比文本相似度实现查重
  16. 2022-2027年中国棉纺织机械行业发展监测及投资战略研究报告
  17. 解决windows下蓝牙设备将休眠中的pc唤醒的困扰
  18. Scheme Language
  19. redis windows版下载教程,及双系统百度网盘资源分享
  20. html电脑自动输出什么意思code,VScode自动生成HTML的含义

热门文章

  1. Ubuntu 18.04 rc.local systemd设置
  2. rm删除报错 :-bash: syntax error near unexpected token `('
  3. Eclipse中,lombok安装
  4. doc 命令查看帮助
  5. 关于java重载函数,参数为null时,调用的处理。(精确性原则)
  6. 【Python-3.5】matplotlib绘制气温折线图
  7. 【SQL】CONNECT BY 层次化查询
  8. Gson转Map时,Int会变成double解决方法
  9. 解决html5中video标签无法播放mp4问题的办法
  10. 解析docker中的环境变量使用和常见问题解决