树的声明:
#include<stdio.h>
#include<stdlib.h>
using namespace std;
typedef char BiElemType;
typedef struct BiTNode{
BiElemType data;
struct BiTNode* lchild;
struct BiTNode* rchild;
}BiTNode,*BiTree;
//树中任何一个节点都是一个结构体,它的空间我们是通过malloc申请出来的。
//tag 辅助队列使用
typedef struct tag{
BiTree p;
struct tag* pnext;
}tag_t,*ptag_t;
二叉树的层次建立
画图理解:
//层次建树
int main(){
BiTree pnew;//存放树的新结点
char c;
BiTree tree=NULL;//建立一棵树,让其为空
ptag_t phead=NULL,ptail=NULL,listpnew=NULL,pcur=NULL;
//phead,ptail是辅助队列的头,尾指针,listpnew指向存放新的队列节点,pcur指向当前元素的双亲节点;
while(scanf("%c",&c)){
if(c=="\n") break;
//calloc(n,m);n 申请空间个数,m申请一个空间的大小;总大小为n*m;
//跟malloc相比,他可以直接将元素赋值为空
pnew=(BiTNode*)calloc(1,sizeof(BiTNode));//申请一个新的树节点 ,并保证左右孩子均为空
pnew->data=c;
listpnew=(tag_t*)calloc(1,sizeof(tag_t));//申请一个新的辅助队列节点
listpnew->p=pnew;//新的辅助队列节点 对应的树元素是 pnew
if(!tree){//树为空,即 pnew为根节点
tree= pnew;//令pnew为根节点
phead=listpnew;ptail=listpnew;//队列头尾都指向此时这个节点的队列节点
pcur=listpnew;
continue;
}
else {//树不为空, 此队列节点依然需要入队
ptail->pnext=listpnew;
ptail=listpnew;
//如果放在左孩子位置,只需要入树即可
if(!pcur->p->lchild)
pcur->p->lchild= pnew;
//如果放在右孩子位置,需要入树且(放入后此节点的两个孩子就全了)双亲节点需要更换为下一个
else if(!pcur->p->rchild){
pcur->p->lchild= pnew;
pcur=pcur->pnext;
}
}
}
return 0;
}
二叉树的前中后序遍历--递归
前序遍历:根左右,中序遍历:左根右 后序遍历:左右根(所谓前中后是根的相对位置,这个也是功能函数所在的位置)
//功能
void visit(BiTree p){
printf("%c",p->data);
}
//前序
void Preorder(BiTree p){
if(p){
visit(p);
Preorder(p->lchild);
Preorder(p->rchild);
}
}
//中序
void INorder(BiTree p){
if(p){
INorder(p->lchild);
visit(p);
INorder(p->rchild);
}
}
//后序
void Postorder(BiTree p){
if(p){
Postorder(p->lchild);
Postorder(p->rchild);
visit(p);
}
}
层次遍历---需要借助队列
层次遍历:一层一层的往下走。又称广度优先遍历
//层次遍历
void Leverorder(BiTree T){
LinkQueue Q;
InitQueue(Q);
EnQueue(Q,T);
BiTree p;
while(!IsEmpty(Q)){
DeQueue(Q,p);//删除存放到p中
putchar(p->data);
if(p->lchild)
EnQueue(Q,p);
if(p->rchild)
EnQueue(Q,p);
}
}
练习题
144. 二叉树的前序遍历
94. 二叉树的中序遍历
102. 二叉树的层序遍历
另外推荐一篇题解:BFS 的使用场景总结:层序遍历、最短路径问题:
本篇over