二叉树的创建、遍历(递归和非递归实现)、交换左右子数、求高度(c++实现)
要求:以左右孩子表示法实现链式方式存储的二叉树(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=0
stack[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=NULL
cout<<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));
}
else
return 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;
}
二叉树的创建、遍历(递归和非递归实现)、交换左右子数、求高度(c++实现)的更多相关文章
- 数据结构二叉树的递归与非递归遍历之java,javascript,php实现可编译(1)java
前一段时间,学习数据结构的各种算法,概念不难理解,只是被C++的指针给弄的犯糊涂,于是用java,web,javascript,分别去实现数据结构的各种算法. 二叉树的遍历,本分享只是以二叉树中的先序 ...
- C实现二叉树(模块化集成,遍历的递归与非递归实现)
C实现二叉树模块化集成 实验源码介绍(源代码的总体介绍):header.h : 头文件链栈,循环队列,二叉树的结构声明和相关函数的声明.LinkStack.c : 链栈的相关操作函数定义.Queue. ...
- 二叉树3种递归和非递归遍历(Java)
import java.util.Stack; //二叉树3种递归和非递归遍历(Java) public class Traverse { /******************一二进制树的定义*** ...
- JAVA递归、非递归遍历二叉树(转)
原文链接: JAVA递归.非递归遍历二叉树 import java.util.Stack; import java.util.HashMap; public class BinTree { priva ...
- 二叉树前中后/层次遍历的递归与非递归形式(c++)
/* 二叉树前中后/层次遍历的递归与非递归形式 */ //*************** void preOrder1(BinaryTreeNode* pRoot) { if(pRoot==NULL) ...
- Java实现二叉树的先序、中序、后序、层序遍历(递归和非递归)
二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的.对于二叉树,有前序.中序以及后序三种遍历方法.因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易 ...
- Java - 二叉树递归与非递归
树的定义具有递归特性,因此用递归来遍历比较符合特性,但是用非递归方式就比较麻烦,主要是递归和栈的转换. import java.util.Stack; /** * @author 李文浩 * @ver ...
- 数据结构-树以及深度、广度优先遍历(递归和非递归,python实现)
前面我们介绍了队列.堆栈.链表,你亲自动手实践了吗?今天我们来到了树的部分,树在数据结构中是非常重要的一部分,树的应用有很多很多,树的种类也有很多很多,今天我们就先来创建一个普通的树.其他各种各样的树 ...
- 数据结构作业——图的存储及遍历(邻接矩阵、邻接表+DFS递归、非递归+BFS)
邻接矩阵存图 /* * @Author: WZY * @School: HPU * @Date: 2018-11-02 18:35:27 * @Last Modified by: WZY * @Las ...
- 二叉树之AVL树的平衡实现(递归与非递归)
这篇文章用来复习AVL的平衡操作,分别会介绍其旋转操作的递归与非递归实现,但是最终带有插入示例的版本会以递归呈现. 下面这张图绘制了需要旋转操作的8种情况.(我要给做这张图的兄弟一个赞)后面会给出这八 ...
随机推荐
- k8s1.4.3安装实践记录(1)-etcd、docker、flannel安装配置
虚拟机:VMware® Workstation 12 Pro 系统:CentOS Linux release 7.2.1511 (Core) 3.10.0-327.el7.x86_64 由于刚开始学习 ...
- java实验四——测试梯形类
package hello; public class TestTixing { public static void main(String[] args) { // TODO Auto-gener ...
- 用Keras搭建神经网络 简单模版(一)——Regressor 回归
首先需要下载Keras,可以看到我用的是TensorFlow 的backend 自己构建虚拟数据,x是-1到1之间的数,y为0.5*x+2,可视化出来 # -*- coding: utf-8 -*- ...
- 关于模板该不该用css强制编辑器文本开头空两格
关于模板该不该用css强制编辑器文本开头空两格这个问题,我很早之前就想说了,写惯了qq日志的童鞋都知道,qq空间的编辑器没有任何css控制,行头空两格是由用户自己控制,我写起日志又像流水账,长长的一篇 ...
- Mysql 於lampp xampp LinuxUbuntu下的配置
默认执行Lampp/Xampp 於Ubuntu下完成后,需要对mysql进行一系列的配置,方可进行更好的操作 lampp下的mysql配置文件路径: /opt/lampp/etc/my.cnf 1 配 ...
- stm32串口接收完整的数据包
参考了文章:<stm32串口中断接收方式详细比较> 文章地址:http://bbs.elecfans.com/jishu_357017_1_1.html 借鉴了第四种中断方式 串口的配置这 ...
- 学习MongoDB 一:MongoDB 入门(安装与配置)
一.简介 MongoDB一种非关系型数据库(NoSql),是一种强大.灵活.可扩展的数据存储方式,因为MongoDB是文档模型,自由灵活很高,可以让你在开发过程中畅顺无比,对于大数据量.高并发.弱事务 ...
- LRU的理解与Java实现
简介 LRU(Least Recently Used)直译为"最近最少使用".其实很多老外发明的词直译过来对于我们来说并不是特别好理解,甚至有些词并不在国人的思维模式之内,比如快速 ...
- 查看shell环境下,网络是否连通-curl/ping
检查网络是否可用 curl www.baidu.com <!--STATUS OK--><html>...</html> ping www.baidu.com注意: ...
- sql 随机取数
Sql server: select top 10 * from 表 order by newid()Access: SELECT top 10 * FROM 表 ORDER BY ...