树的先序遍历
typedef struct{/二叉树的链式存储结构
elemtype data;
btnode *lchild,*rchild;//左右孩子指针域
}btnode,*btree;
void visit(btnode *t){
cout<<t->data<<endl;
}
递归
void preorder(btnode *t){//递归先序遍历
while(t){
visit(t);
preorder(t->lcjild);//遍历左子树
preorder(t->rchild);//遍历右子树
}
}
非递归
void preorder(btnode *t){
btnode *stack[max];
int top=-1;
btnode *p=t;
while(p!=null){
stack[++top]=p;//初始化。根入栈
while(top>-1){//栈不空时循环
p=stack[top--];//p指向栈顶元素
visit(p);//访问栈顶元素
if(p->rchild){stack[++top]=p->rchild;}//当前节点的有孩子入栈
if(p->lcjild){stack[++top}=p->lchild;}//若左孩子不空,入栈左孩子
}//while
}//while
}
void preorder(btnode *t){//非递归先序遍历
btnode *stack[max];
int top=0;
btnode *p=t;
do{
while(p!=null){
stack[top++]=p;
visit(stack[top]);//访问栈顶元素
p=p->lchild;
}
while(top>0){
top--;
p=stack[top];
p=p->rchild;
}
}while(p!=null||top>0)
}
树的中序遍历
递归算法
void midorder(btnode *t){
while(t){
midorder(t->lchild);
visit(t);
midorder(t->rchild);}
}
非递归算法(入栈一直向左走,出栈访问右子树)
void midordedr(btnode *t){
//非递归
btnode* stack[max];
btnoder *p=t;//工作指针
top=0;//初始化栈
do{
while(p){
stack[top++]=p->lchild;
p=p->lchild;
}
while(top>0){
visit(stack[top--]);//访问栈顶元素并出栈栈顶元素
p=stack[top];
p=p->rchild;
}
}while(t!=null||top>0)
}
树的后序遍历
递归
void postorder(btnode *t){
while(t){
postorder(t->lchild);
postorder(t->rchild);
visit(t);
}
}
非递归
算法思想:从根节点开始一直朝左遍历树,直至数的左子树为空,此时看树的右子树是否为空,若为空,则出栈栈顶元素并访问,top--,遍历指针重新指向栈顶元素,若是存在右子树并且当前右子树已经被访问过了,则出栈当前元素并访问,top--,遍历指针重新指向栈顶元素,若存在右子树并且尚未被访问过,遍历指针指向右子树并入栈,重复前面的步骤,直到栈空并且树被遍历完结束。
void postorder(btnode *t){
btnode *stack[max];
int top=-1;
btnode *p=t;
btnode *pre=NULL;
bool visited=false;
if(t){//树不空时进行遍历
stack[++top]=t;//初始化栈顶元素
while(top>-1){//栈不空时进行循环
p=stack[top];
if(p->lchild){//p的右子树若不空,一直入栈
stack[++top]=p->lchild;}
}else if(p->lchild==NULL || visited){//左子树为空或已经被访问过
visited=false;
if(p->rchild==NULL||(p-rchild!=NULL&&pre==p->rchild)){
//右子树为空或者当前右子树已经被访问过了
visit(p);//访问当前结点
pre=p;//更新
top--;
visited=true;//已经被访问过的标记
}else if(p-rchild && pre!=p->rchild){
//右子树存在,并且当前的右子树尚未被访问过
stack[++top]=p->rchild;//入栈右子树}
}//if
}/while
}
遍历算法的应用
1、求叶子
//方法一
int leaf(btnode *t) {
while(t){
if(t->lchild==NULL&&t->rchild==NULL){
n++;
return n;}
leaf(t->lchild);
leaf(t->rchild);
}
}
//方法二
int leaf(btnode *t){
int n;
if(!t){
n=0;
}else if(t->lchild!=null||p->rchild!=null){
n=leaf(t->lchild)+leaf(t->rchild)}
else{
n++;}
return n;
}
}
2、求树高
分别求左树的高和右数的高,再做比较
//方法一
void postbitreedepth(btnode *t){
int hl,hr,max;
if(t){
postbitreedepth(t->lchild);//求左子树的深度
postbitreedepth(t->rchild);//求右子树的深度
max=hl>hr:hl?hr;
return(max+1);//返回树的深度}
else return(0);
}
//方法二
void postbitreedepth(btnode *t,int level,int &depth){
/*t只想二叉树的根的指针,level是当前所指结点的层次,初始为1,depth是当前所求得的的最大数深度,开始为0*/
if(t){
if(level>depth) depth=level;
postbitreedepth(t->lchild;level+1;depth);
postbitreedepth(t->rcild;level+1;depth);
}else return(0);
}
3、在二叉树上查找某个结点
bool locate(btnode *t,elemtype x,btnode *p){
if(t==null)
{p=null;
return false;}
while(t){
if(t->data==x) {
p=t;
return true;}
if(locate(t->lchild)) {
p=t->lchild;
return true;}else return(locate(t->rchild));
}
}
4、复制二叉树
算法思想:利用后序遍历的思想,先复制左右子树,再生成一个新的根节点。
//后序遍历复制二叉树
//复制二叉树
Bitree *gettreenode(elemtype i,BiTnode *l,BiTnode *r){
//生成一个元素值为i,左指针为l,右指针r的结点
T=new BiTnode;
T->data=i;
T->lchild=l;
T-rchild=r;
return T;
}
BiTree copytree(BiTnode *T){
//复制二叉树T
if(!T) return NULL;
if(T->lchild)//复制左孩子
{nl=newcopytree(T->lchild);}
else nl=null;//否则左孩子为空
if(T->rchild!=null){//复制右孩子
nr=copytree(T->rchild);}
else nr=null;//否则右孩子置空
T=gettreenode(T->node,T->lchild,T->rchild);//生成根节点
return T;
}
}
树的层序遍历(队列)
void levelorder(BiTree t){
Quequ Q;
InitQueue(Q);//初始化一个队列
BiTree p;//工作指针
Enqueue(Q,t)//将根节点入队
while(!isEmpty(Q)){//队列不空时
Dequeue(Q,p)//出队队头元素给p
visit(p);//访问p
if(p->lchild!=null){//若左子树不空,入队
Enqueue(Q,p->lchild);}
if(p->rchild!=null){//ruo右子树不空,入队右子树
Enqueue(Q,p);}
}
}