二叉树的创建与各种遍历详解
来源:互联网 发布:指纹考勤机软件 编辑:程序博客网 时间:2024/06/07 03:13
二叉树大部分高级数据结构的基础,对这种基础的数据结构要达到非常熟练顺手拈来的程度才能对问题有更深一步的理解,今天为了巩固树这一部分,把二叉树的基本操作,建树,各种递归、非递归遍历,求叶子节点个数都做了详细的理解,以达到熟练的程度。
1,二叉树的结构定义:
typedef struct LNode {int data; //节点的值LNode *Left; //指向做孩子LNode *Right;//指向右孩子}*Tree;
2,二叉树的创建:采用递归前序建树,如果节点为空,则值为零,也就是虚节点,这里我为了简便。
//初始化二叉树
void CreateTree(Tree &L){LNode *p;int temp;cin>>temp;if(temp==0) L=NULL;else{L=(Tree)malloc(sizeof(LNode));L->Left=NULL;L->Right=NULL;L->data=temp;CreateTree(L->Left);//创建左孩子CreateTree(L->Right);//创建右孩子}}
创建二叉树采用的先序序列,根——>左——>右 ,刚开始调用函数的时候传的参数(注意为什么要传引用?)是一个节点,如果这个节点值不为零,则这个节点存在,然后创建这个节点,then,创建左孩子CreateTree(L->Left),紧接着创建右孩子CreateTree(L->Right)
3,二叉树的三种顺序的遍历:
前序:根——>左——>右
中序:左——>根——>右
后序:左——>右——>根
具体操作就看课本吧,直接实现代码,只有后序在非递归遍历的时候稍微麻烦一点
前序递归遍历:
//前序递归遍历
void Pre(Tree T){if(T){cout<<T->data<<" ";Pre(T->Left);Pre(T->Right);}else return ;}
前序非递归遍历:
由于前序必须先遍历各节点之后才能使左孩子节点,然后才是右节点,我们不用递归这里只有用栈stack把,每走一步把气左孩子还有孩子先存入栈中,等根节点都遍历完之后,开始回溯遍历其左节点,,然后右节点,具体实现如下:
//前序非递归遍历void Pre1(Tree T){stack<Tree> sqstack;Tree p;sqstack.push(T);while(!sqstack.empty()){p=sqstack.top();sqstack.pop();if(p){cout<<p->data<<" ";sqstack.push(p->Right);sqstack.push(p->Left);}}}
中序递归遍历:
//中序递归遍历void Mid(Tree T){if(T){Mid(T->Left);cout<<T->data<<" ";Mid(T->Right);}}
中序非递归遍历:
中序遍历必须先遍历左节点,然后根节点,所以我们必须先找到最后一个左节点,这个节点没有左节点,然后才能把它输出,输出之后,由于没有左节点,所以要遍历右节点,把有节点看作小二叉树的根节点,继续找最后的一个左节点,然后弹出栈并输出,从栈里取出的每个元素都一次这样操作,知道节点为空或者栈为空的时候,程序终止
//中序的非递归遍历void Mid_N(Tree T){stack<Tree> sqstack;Tree p;p=T;if(!p) {cout<<"树为空"<<endl;return ;}while(!sqstack.empty()||p!=NULL){while(p){sqstack.push(p);p=p->Left;}if(!sqstack.empty()){p=sqstack.top();sqstack.pop();cout<<p->data<<" ";p=p->Right;}}}
后序递归遍历:
//后序递归遍历void Back(Tree T){if(T){Back(T->Left);Back(T->Right);cout<<T->data<<" ";}}
后序非递归遍历:
我们依然用栈实现,只是这个时候,根节点在栈里可能两次被访问,但是此时如果没有遍历其右节点,根节点是不能出栈的,所以这里要做一下控制,我们定义了一个变量,用来存储上次访问的节点。然后我们分析一下当前节点可以出栈并输出的情况:当其左孩子和右孩子都为空的时候,或者上次访问的节点不为空,且为其左孩子节点或右孩子节点的时候,此时这个节点可以出栈。(这个可以想想为什么不是上次访问的节点只有是右孩子的时候才可以出栈?)
//后续非递归遍历void Back_N(Tree T){stack<Tree> sqstack;Tree cur;Tree pre=NULL;sqstack.push(T);while(!sqstack.empty()){cur=sqstack.top();if((cur->Left==NULL&&cur->Right==NULL)||(pre!=NULL&&(pre==cur->Left||pre==cur->Right))){cout<<cur->data<<" ";sqstack.pop();pre=cur;}else{if(cur->Right)sqstack.push(cur->Right);if(cur->Left)sqstack.push(cur->Left);}}}
叶子节点的个数:
也就是一个节点不为空,且其左孩子和右孩子都为空的节点的个数
//求叶子节点的个数int Node_Sum(Tree T){static int sum=0;if(T->Left)Node_Sum(T->Left);if(T->Right)Node_Sum(T->Right);if(T->Left==NULL&&T->Right==NULL){sum++;return sum;}return sum;}
释放空间:
开辟了空间肯定要释放的
//释放开辟的内存void FreeTree(Tree &T){if(T){FreeTree(T->Left);FreeTree(T->Right);free(T);}}
完整代码贴出:
//二叉树前中后,以及递归和非递归遍历#include<iostream>#include<cstdio>#include<stack>using namespace std;typedef struct LNode {int data; //节点的值LNode *Left; //指向做孩子LNode *Right;//指向右孩子}*Tree;//创建一棵二叉树Lvoid CreateTree(Tree &L){LNode *p;int temp;cin>>temp;if(temp==0) L=NULL;else{L=(Tree)malloc(sizeof(LNode));L->Left=NULL;L->Right=NULL;L->data=temp;CreateTree(L->Left);CreateTree(L->Right);}}//前序递归遍历void Pre(Tree T){if(T){cout<<T->data<<" ";Pre(T->Left);Pre(T->Right);}else return ;}//中序递归遍历void Mid(Tree T){if(T){Mid(T->Left);cout<<T->data<<" ";Mid(T->Right);}}//后序递归遍历void Back(Tree T){if(T){Back(T->Left);Back(T->Right);cout<<T->data<<" ";}}//前序非递归遍历void Pre1(Tree T){stack<Tree> sqstack;Tree p;sqstack.push(T);while(!sqstack.empty()){p=sqstack.top();sqstack.pop();if(p){cout<<p->data<<" ";sqstack.push(p->Right);sqstack.push(p->Left);}}}//中序的非递归遍历void Mid_N(Tree T){stack<Tree> sqstack;Tree p;p=T;if(!p) {cout<<"树为空"<<endl;return ;}while(!sqstack.empty()||p!=NULL){while(p){sqstack.push(p);p=p->Left;}if(!sqstack.empty()){p=sqstack.top();sqstack.pop();cout<<p->data<<" ";p=p->Right;}}}//后续非递归遍历void Back_N(Tree T){stack<Tree> sqstack;Tree cur;Tree pre=NULL;sqstack.push(T);while(!sqstack.empty()){cur=sqstack.top();if((cur->Left==NULL&&cur->Right==NULL)||(pre!=NULL&&(pre==cur->Left||pre==cur->Right))){cout<<cur->data<<" ";sqstack.pop();pre=cur;}else{if(cur->Right)sqstack.push(cur->Right);if(cur->Left)sqstack.push(cur->Left);}}}//求叶子节点的个数int Node_Sum(Tree T){static int sum=0;if(T->Left)Node_Sum(T->Left);if(T->Right)Node_Sum(T->Right);if(T->Left==NULL&&T->Right==NULL){sum++;return sum;}return sum;}//释放开辟的内存void FreeTree(Tree &T){if(T){FreeTree(T->Left);FreeTree(T->Right);free(T);}}int main(){//stack<Tree> sqstack;Tree tree;CreateTree(tree); //建树cout<<"前序遍历"<<endl;Pre(tree);cout<<endl;Pre1(tree);cout<<endl;cout<<"中序遍历"<<endl;Mid(tree); // 中序递归遍历cout<<endl;Mid_N(tree); //中序非递归遍历cout<<endl;cout<<"后序递归遍历"<<endl;Back(tree);cout<<endl;cout<<"后序非递归遍历"<<endl;Back_N(tree);cout<<endl;cout<<"叶子节点的个数"<<endl;cout<<Node_Sum(tree)<<endl;FreeTree(tree); //释放树return 0;}
- 二叉树的创建与各种遍历详解
- 二叉树的创建与各种遍历方式
- 二叉树的创建以及各种遍历
- 二叉树的创建和各种遍历方法
- 二叉树创建及各种遍历的实现
- 二叉树的创建及各种遍历操作
- java实现二叉树的创建和各种遍历操作
- 二叉树的创建与遍历
- 二叉树的创建与遍历
- 二叉树的创建与遍历(递归)
- 二叉树的创建与遍历
- 二叉树的创建与遍历
- 二叉树的创建与遍历
- 二叉树的创建与遍历
- 二叉树的遍历与创建
- 二叉树的创建与遍历
- 二叉树的创建与层次遍历
- 二叉树的创建与递归遍历
- SQL 查找重复记录
- 正多边形
- 如何分析挖掘竞争对手的方针方法与策略
- HDU-2600
- 有向图 强连通分量
- 二叉树的创建与各种遍历详解
- CentOS 6.3下Samba服务器的安装与配置
- 获取iframe中的网页内容(同域名下)
- WinForm程序的界面多语言切换
- 【jiasuba】做好八点预防工作 黑客入侵没门
- vc++ 加了加入GDIPlus.lib链接库问题,无法从“Gdiplus::Rect *”转换为“const Gdiplus::Rect”
- linux网络有线连接失败“设备未托管” 解决办法
- 五只猴子采得一堆桃子,半夜里第一只猴子偷偷起来把桃平均分成五分,发现还多一个,它吃了哪个桃子,还拿走其中的一份,第二只猴子起来又把桃子分成五分,还多一个,它吃了那个桃子,有拿走其中的一份,第三第四第五
- QQ空间魔力日志源代码