二叉树的三种遍历方式(递归算法)
I、先序遍历(每个子树的根结点最先遍历)
//T为树的某个结点
//lchild为左子结点,rchild为右子结点
void PreOrder(Tree T){
if(T!=NULL)
{
visit(T);
PreOrder(T->lchild);
PreOrder(T->lchild);
}
}
访问顺序为(左子结点->右子结点->根结点)
1->2->4->5->3->6
II、中序遍历(每个子树的根结点不最先也不最后的遍历)
void InOrder(T)
{
if(T!=NULL)
{
InOrder(T->lchild);
visit(T);
InOrder(T->rchild);
}
}
访问顺序为(左子结点->根结点->右子结点)
4->2->5->1->6->3
III、后序遍历(根结点最后遍历)
void PostOrder(T)
{
if(T!=NULL)
{
PostOrder(T->lchild);
PostOrder(T>rchild);
visit(T);
}
}
访问顺序为(左子结点->右子结点->根结点)
4->5->2->6->3->1
遍历二叉树的非递归算法
I、中序遍历(栈)
懒得用文字描述过程了,上代码
void InOrder(T)
{
InitStack(S);
while(p!=NULL||IsEmpty(S))
{
if(p)
{
Push(S,p);(将p结点入栈)
p=p->lchild;
}
else
{
Pop(S,p);(出栈)
visit(p);
p=p->rchild;
}
}
}
II、层次遍历(队列)(广度优先搜索)
懒得写代码了,上文字
算法思想:
1)初始将根入队并访问根结点,然后出队(先入队再访问)
2)若有左子树,将左子树的根入队;
3)若有右子树,将右子树的根入队;
4)然后出队,访问该结点
5)反复直到队列为空
(脑中要有一张图,一边入队,另一边出队)
由遍历序列构造二叉树
1、只有一种遍历序列不能确定一棵二叉树。
2、后/先序和中序可以确定一棵。(这里的“和”是组合,是一起用)
3、先序和后序不能确定一棵。
4、层次遍历加中序也可以确定一棵
5、具体实现方法以后再来完善(咕咕咕)
二叉树的四种建树方式
先序建树、中序建树、后序建树
这三种建树方式与之前同序的遍历方式的代码几乎一样,只是将访问的那一步变成申请内存空间和将值存入结点(还要判断是否应在该处将值存入)
层序建树
也是用队列,但比遍历要麻烦一点,直接放代码
tree *Create()
{
queue<tree*>q;//层序遍历中需要的队列
tree *t,*head,*temp;
if(v.empty())//数组为空
{
return NULL;
}
t=(tree*)malloc(sizeof(tree));
t->data=v.front();//建立根结点
v.pop();//将数组第一个元素去掉
head=t;//存下根结点,方便return
q.push(t);//将该结点入队
while(q.size())//存结点的队列不为空
{
temp=q.front();//记录队列头部元素
q.pop();//出队
temp->lchild=NULL;//先把儿子结点定为NULL
temp->rchild=NULL;
if(v.size())//建立左儿子结点
{
t=(tree*)malloc(sizeof(tree));
t->data=v.front();//建立结点
v.pop();//去掉数组首元素
temp->lchild=t;//将该子结点与双亲结点连上
q.push(t);//将该结点入队
}
if(v.size())//建立右儿子结点
{
t=(tree*)malloc(sizeof(tree));
t->data=v.front();
v.pop();
temp->rchild=t;
q.push(t);
}
}
return head;
}
求树深度
从别人那学到的方法,比我自己写的要简洁多了
int Height(tree *t)//t为该树的根结点
{
if (t==NULL)
{
return 0;
}
return max(Height(t->lchild),Height(t->rchild))+1;
}