Loading

树算法题

目录

1、计算二叉树中所有结点个数

2、计算二叉树中所有叶子节点的个数

3、计算二叉树中所有双分支的节点个数

4、计算二叉树的深度

5、找出二叉树中最大值的点

6、判断两个二叉树是否相似(指都为空或者都只有一一个根节点,或者左右子树都相似)

7、把二叉树所有节点左右子树交换

8、输出先序遍历第k个结点的值

9、求二叉树中值为x的层号

10、树中元素为x的结点,删除以它为根的子树

11、先序非递归遍历二叉树

12、中序非递归遍历二叉树

13、后序非递归遍历二叉树

14、计算二叉树的带权路径长度

15、找到p和q最近公共祖先结点r

16、层次遍历

17、判断二叉树是否为完全二叉树

1、计算二叉树中所有结点个数

int CntNode(BiTree T){
    int k=0;
    if(T){
        k++;
        k+=CntNode(T->lchild);
        k+=CntNode(T->rchild);
    }
    return k;
}

2、计算二叉树中所有叶子节点的个数

int LeafNode(BiTree T){
    int k=0;
    if(T){
        if(T->lchild==NULL&&T->rchild==NULL)
            k++;
        else{
            k+=LeafNode(T->lchild);		//统计左子树叶子结点
            k+=LeafNode(T->rchild);		//统计右子树叶子结点
        }
    }
    return k;
}

3、计算二叉树中所有双分支的节点个数

int DNodes(BiTree T){
    if(T==NULL)
        return 0;
    else if(T->lchild!=NULL&&T->rchild!=NULL)//双分支结点
        return DNodes(T->lchild)+DNodes(T->rchild)+1;
    else//单分支结点或叶子结点
        return DNodes(T->lchild)+DNodes(T->rchild);
}

4、计算二叉树的深度

int Deepth(BiTree T){
    int hl=0,hr=0;	//hl是左子树高度,hr是右子树高度
    if(T==NULL)
        return 0;
    else{	
        hl=Deepth(T->lchild);	//遍历左子树求高度
        hr=Deepth(T->rchild);	//遍历右子树求高度
        return hl>hr?hl+1:hr+1;	//返回子树高度较高的+根结点
    }
}

5、找出二叉树中最大值的点

//基于中序遍历的非递归算法
ElemType Inorder(BiTree T){
    ElemType max=-1;
    InitStack(S);
    p=T;
    while(p||!StakEmpty(S)){
        if(p){
            p=p->lchild;
            Push(S,p);	//入栈
        }
        else{
            Pop(S,p);	//出栈
            if(p->data>max)
                max=p->data;
            p=p->rchild;
        }
    }
    
    return max; 
}



6、判断两个二叉树是否相似(指都为空或者都只有一一个根节点,或者左右子树都相似)

bool IsSimilar(BiTree T1, BiTree T2){
    if(T1==NULL&&T1==NULL)	//都为空树
        return true;
    else if(T1==NULL||T1==NULL)	//只有一个棵树为空
        return false;
    else	//递归判断子树
        return IsSimilar(T1-lchild,T2->lchild) && IsSimilar(T1-rchild,T2->rchild);
}

7、把二叉树所有节点左右子树交换

/**
	先交换左子树中的结点
	再交换右子树中的结点
	最后交换左右子树,基于后序遍历
**/

void SwaptTree(BiTree T){
    BiTree temp;
    if(T){
        SwaptTree(T->lchild);	//递归交换左子树
        SwaptTree(T->rchild);	//递归交换右子树
        temp=T->lchild;
        T->lchild=T->rchild;
        T->rchild=temp;
    }
}

8、输出先序遍历第k个结点的值

int cnt=0;	//全局变量,统计结点个数
Status pre_k(BiTree T,int k){
    if(T){
        cnt++;
        if(cnt==k){
            print(T->data);	//输出第k个结点的值
            return OK;
        }
        else{
            if(pre_k(T->lchild,k))
                return OK;
            if(pre_k(T->rchild,k))
                return OK;
        }
    }
    return ERROR;
}

9、求二叉树中值为x的层号

int h=1;
void levelnum(BiTree T,ElemType x){
    if(T){
        if(x==T->data)
            cout<<h;	//打印层号
        ++h;
        levelnum(T->lchild,x);
        levelnum(T->rchild,x);
        --h;
    }
}

10、树中元素为x的结点,删除以它为根的子树

void Del_x(BTree T)//基于后序递归遍历删除结点
{
    if(T)
    {
        Del_x(T->lchild);
        Del_x(T->rchild);
        free(T);
    }
}

//基于层序遍历
void Search(BTree T,TElemType x){
    SqQueue Q;//定义顺序队列
    InitQueue(Q);//初始化队列
    BTree p;
    if(T){
        if(T->data==x){
            Del_x(T);
            exit(0);
        }
        EnQueue(Q,T);
        while(!QueueEmpty(Q)){
            DeQueue(Q,p);
            if(p->lchild){
                if(p->lchild->data==x){
                    Del_x(p->lchild);
                    p->lchild=NULL;//恢复树的结构
                }
                else
                    EnQueue(p->lchild);
            }
            if(p->rchild){
                if(p->rchild->data==x){
                    Del_x(p->rchild);
                    p->rchild=NULL;//恢复树的结构
                }
                else
                    EnQueue(p->rchild);
            }
        }
    }
}

11、先序非递归遍历二叉树

void PreOrder(BiTree T){
    InitStack(S);
    p=T;
    while(p||!StackEmpty(S)){
        if(p){
            Visit(p);
            p=p->lchild;
            Push(S,p);
        }
        else{
            Pop(S,p);
            p=p->rchild;
        }
    }
}

12、中序非递归遍历二叉树

void InOrder(BiTree T){
    InitStack(S);
    p=T;
    while(p||!StackEmpty(S)){
        if(p){
            p=p->lchild;
            Push(S,p);
        }
        else{
            Pop(S,p);
            Visit(p);
            p=p->rchild;
        }
    }
}

13、后序非递归遍历二叉树

void PostOrder(BiTree T){
	InitStack(S);	//初始化栈
    p=T;r=NULL;	//r指向上一个被访问的结点
    while(p||!StackEmpty(S){
       	if(p){
            Push(S,p);
            p=p->rchild;	//一直走到最左边
        }
        else{
            GetTOP(S,p);	//查看栈顶元素
            if(p->rchild&&p->rchild!=r)
                p=p->rchild;
            else{
                Pop(S,p);
                Visit(p);
                r=p;	//r记录被访问的结点
                p=NULL;	//清空p结点
            }
        }
    }
}

14、计算二叉树的带权路径长度

typedef struct BTNode{
    int weight;
    struct BTNode *lchild,*rchild;
}BTNode,*BiTree;

int WPL=0;	//全局变量求带权路径长度
int get_wpl(BiTree T, int deep){	//deep初始值为1
    if(T){
        get_wpl(T->lchild,deep+1);	//中序遍历左子树
        if(T->rchild==NULL&&T->lchild==NULL)
            WPL+=(deep-1)*T->weight;
        get_wpl(T->rchild,deep+1);	//中序遍历右子树
    }    
}

15、找到p和q最近公共祖先结点r

/*
以二链表存储的二叉树上找某结点的所有祖先,某两个结点的最近公共祖先,从根结点到某结点的路径,根结点到每个叶子结点以及最远叶子的路径等。均应采取后序非递归遍历。因为后序遍历最后访问根结点,当访问到某结点时,栈中所有元素均为该结点的祖先。
找p和q的最近共同祖先结点r,不失一般性,设p在q的左边。后序遍历必然先遍历到结点p,栈中元素均为p的祖先。将栈复制到另一辅助栈中再继续遍历到结点q时,将中元素从栈顶开始逐个到辅助中去匹配,第一个匹配(即相等)的元素就是结点p和g的最近公共祖先。
*/

typedef struct {
    BiTree t;
    int tag;	//tag=0表示左孩子已被访问,1表示右孩子已被访问
}Stack;

BiTree Ancestor(BiTree T,BiTNode *p,BiTNode *q){
    Stack s[],s1[];	//栈,容量足够大
    top=0,top1=0;	//栈顶指针,top1是s1的栈顶指针
    bt=T;
    while(bt!=NULL||top>0){
        while(bt!=NULL && bt!=p && bt!=q){
            s[++top].t=bt;
            s[top].tag=0;
            bt=bt->lchild;
        }
        if(bt==p){//假定p在q的左侧,遇结点p 时,栈中元素均为p的祖先结点
            for(i=1;i<=top;i++)//将p的祖先结点放到辅助栈s1中
                s1[i]=s[i];
            top1=top;	//修改栈顶指针
        }
        if(bt==q){//找到q结点
            for(i=top;i>0;i--){//将栈中元素到s1去匹配
                pp=s[i].t;
                for(j=top1;j>0;j--){
                    if(s1[j].t==pp){
                        cout<<"共同祖先已找到";
                        return pp;
                    }//if
                }//for
            }//for
        }//if
        while(top!=0&& s[top].tag==1) top--;	//退栈
		if(top!=0){s[top].tag=1;bt=s[top].t->rchild;}	//沿右分支向下遍历
    }
    return NULL;
}

16、层序遍历

void LevelTraverse(BiTree T)
{
	int i, j;
	BiTree p[100];					//树指针数组,用来模拟队列 
	
	i = j = 0;
	
	if(T)
		p[j++] = T;
		
	while(i<j)
	{
		printf("%c ", p[i]->data);
		if(p[i]->lchild)
			p[j++] = p[i]->lchild;
		if(p[i]->rchild)
			p[j++] = p[i]->rchild;
		i++;		
	}
}

void LevelTraverse(BiTree T)
{
	if(T){
        InitQueue(Q);	//初始化队列
 		EnQueue(Q,T);	//入队
        while(!QueueEmpty(Q)){
            DeQueue(Q,p);
            Visit(p);
            if(p->lchild)
                EnQueue(p->lchild);
            if(p->rchild)
                EnQueue(p->rchild);
        }
    }
}


17、判断二叉树是否为完全二叉树

//基于层序遍历,将所有结点入队,包括空结点,结点出队时若当前结点为空,则判断后一结点,后一结点不空则不是完全二叉树(不满足完全二叉树的形状)。

bool isCompleteTree(BiTree T){
    if(T==NULL)
        return true;
    InQueue(Q);
    EnQueue(Q,T);
    while(!QueueEmpty(Q)){
        DeQueue(Q,p);
        if(p){		//所有结点入队,包括空结点
            EnQueue(Q,p->lchild);
            EnQueue(Q,p->rchild);
        }
        else{
            while(!QueueEmpty(Q)){
                DeQueue(Q,p);
                if(p)
                    return false;	//不是完全二叉树
            }
        }
    }
    return true;
}


18、层序遍历求二叉树高度

int deepth(BiTree T){
    if(T==NULL)
        return 0;
    //初始化队列
    BiTree Q[maxsize];
    int level=0,last=0;	//last指向每层最右结点
    int front=-1,rear=-1;
    Q[++rear]=T;	//根节点入队
    BiTree p;
    while(front<rear){	//队列非空
        p=Q[++front];	//出队
        if(p->lchild)
            Q[++rear]=p->lchild;
        if(p->rchild)
            Q[++rear]=p->rchild;
        if(last==rear){
            level++;	//层数+1
        	last=rear;	//last指向下层
        }   
    }
    return level;
}

posted @ 2023-11-16 19:26  记录学习的Lyx  阅读(21)  评论(0编辑  收藏  举报