二叉树(附带一点森林的代码)

        以下为本人自己总结整理的常考的二叉树的相关伪代码(C语言),部分题目未整理有待补充,且可能存在错误,欢迎批评指正!

目录

(一)二叉树

1、基础类题目

        ●二叉树的二叉链式存储定义

        ●初始化二叉链表

        ●二叉树的顺序存储定义(有待补充)

        ●求二叉树结点个数

        ●求二叉树叶子结点个数

        ●求二叉树叶子结点个数、度为1的结点个数、度为2的结点个数(二叉链表存储)

        ●求二叉树高度/深度(递归实现)

        ●基于二叉链表存储,求二叉树高度/深度(采用层次遍历、非递归实现)

        ●基于二叉链表存储,求二叉树中根为x的子树的深度(层次遍历+队列)

        ●求二叉数第k层结点个数

        ●递归实现二叉树的先、中、后序遍历

        ●借助栈非递归实现二叉树的先、中、后序遍历

        ●二叉树的自上而下自左至右的一般层次遍历(用队列的函数编写的非递归算法)

        ●二叉树的自下而上自右至左的层次遍历【栈的应用】

2、构建类题目

        ●已知二叉树的先序和中序序列,编写算法建立二叉树的二叉链链表(待补充)

3、判断类题目

        ●借助队列,二叉树以二叉链表存储,非递归判断一棵二叉树是否为完全二叉树(层次遍历的变形)

        ●二叉树以二叉链表形式存储,判断二叉树是否为二叉排序树(有点问题,仅供参考)

        ●二叉树以二叉链表形式存储,判断两棵二叉树是否同构(有待补充)

4、查找类题目

        ●递归实现二叉树中按值查找(有待补充)

        ●二叉树采用二叉链表存储结构,求先序遍历序列中第k个结点的值(有待补充)

        ●求一般二叉树中两个结点的最近公共祖先(结点值均唯一)

        ●求一棵给定节点至根节点的路径【栈的应用】

5、距离类题目

        ●求一棵树的最大宽度(有待补充)

        ●求二叉树的叶结点的带权路径长度WPL(有待补充)

6、其他

        ●二叉链式存储的二叉树,交换每个结点的左右孩子/左右子树-即二叉树的镜像

(二)森林

        ●求孩子-兄弟表示法存储的森林的叶子结点数

(一)二叉树

1、基础类题目

●二叉树的二叉链式存储定义
typedef struct BTNode{
    ElemType data;
    Struct BTNode *lchild,*rchild;
}BTNode,*BiTree;
●初始化二叉链表
bool InitBiTree(BiTree &T){
    ElemType ch;
    cin>>ch;//输入元素ch
    if(ch==“#”)T=NULL;
    else{
        T=(BTNode*)malloc(sizeof(BTNode));
        T→data=ch;
        InitBiTree(T→lchild);
        InitBiTree(T→rchild);
    }
}
二叉树的顺序存储定义(有待补充)
求二叉树结点个数
int c=0;//c记录结点的个数
    int CountNode(BiTree T){
    if(T!=NULL){
        CountNode(T→lchild);
        CountNode(T→rchild);
        c++;
    }
    return c;
}

int CountNode(BiTree T){
    if(T==NULL)return 0;
    int lc=CountNode(T→lchild);//lc记录左子树结点个数,
    int rc=CountNode(T→rchild);//rc记录右子树结点个数
    return lc+rc+1;//结点个数=左子树个数+右子树个数+根结点
}
●求二叉树叶子结点个数
int LeafNum1(BiTree T){//法一
    int lc=0,rc=0;//lc记录左子树结点个数,rc记录右子树结点个数
    if(T==NULL)return 0;
    lc=LeafNum1(T→lchild);
    rc=LeafNum1(T→rchild);
    if(lc==0&&rc==0)return 1;
    return lc+rc;
}

int n0=0;//记录叶子结点数
int LeafNum2(BiTree T){//法二
    if(T!=NULL){
        LeafNum2(T→lchild);
        LeafNum2(T→rchild);
        if(T→lchild==NULL&&T→rchild==NULL)n0++;
    }
    return n0;
}
求二叉树叶子结点个数、度为1的结点个数、度为2的结点个数(二叉链表存储)
int n0=0,n1=0,n2=0;//定义变量记录度为0/1/2的结点个数
int NumCount(BiTree T){
    if(T!=NULL){
        NumCount(T→lchild);
        NumCount(T→rchild);
        if(T→lchild==NULL&&T→rchild==NULL)n0++;
        if((T→lchild==NULL&&T→rchild!=NULL)||(T→lchild!=NULL&&T→rchild==NULL))n1++;
        if(T→lchild!=NULL&&T→rchild!=NULL)n2++;
    }
    return 0;//结束
}
●求二叉树高度/深度(递归实现)
int TMaxDepth(BiTree T){//或BTNode root
    if(T==NULL)return 0;
    int ld=TDepth(T→lchild);//定义变量记录左子树高度
    int rd=TDepth(T→rchild);//定义变量记录右子树高度
    return ld>rd?ld+1:rd+1;
}
●基于二叉链表存储,求二叉树高度/深度(采用层次遍历、非递归实现)
int TMaxDepth(BiTree T){
    if(T==NULL)return 0;
    int level=0,last=0;//level记录当前所在的层数,last指向当前层的最右结点
    int front=-1,rear=-1;
    BiTree Q[QueueMaxSize];
    BiTree t;
    Q[++rear]=T;//根结点入队
    while(front<rear){
        t=Q[++front];
        if(t→lchild!=NULL)Q[++rear]=t→lchild;
        if(t→rchild!=NULL)Q[++rear]=t→rchild;
        if(front==last){
            level++;
            last=rear;//last指向下一次
        }
    }
    return level;
}
●基于二叉链表存储,求二叉树中根为x的子树的深度(层次遍历+队列)
int TMaxDepth(BiTree T){
    if(T==NULL)return 0;
    int ld=TDepth(T→lchild);//定义变量记录左子树高度
    int rd=TDepth(T→rchild);//定义变量记录右子树高度
    return ld>rd?ld+1:rd+1;
}

int Depth_x(BiTree T,int x){//借助层次遍历+队列+非递归
    Queue Q;
    InitQueue(Q);
    EnQueue(Q,T);//根结点入队
    BiTree t;
    while(!isEmpty(Q)){
        DeQueue(Q,t);//出队,队头元素赋值给t
        if(t.data==x)return TMaxDepth(t);
        if(t→lchild!=NULL)EnQueue(Q,t→lchild);
        if(t→rchild!=NULL)EnQueue(Q,t→lchild);
    }
    return 0;
}

int Depth_x(BiTree T,int x,int depth){//递归
    if(T=NULL)return 0;
    if(T→data==x)return depth+1;
    int ld=Depth_x(T→lchild,x,depth+1);
    if(ld>0)return ld;
    return Depth_x(T→rchild,x,depth+1);
}
●求二叉数第k层结点个数
int NlevelTree(BiTree T,int k){
    int lc=0,rc=0;//记录左右子树结点个
    if(T==NULL||k==0)return 0;
    if(k==1)return 1;
    lc=NlevelTree(T→lchild,k-1);
    rc=NlevelTree(T→rchild,k-1);
    return lc+rc;
}
●递归实现二叉树的先、中、后序遍历
void PreOrder(BiTree T){//先序
    if(T==NULL)return;
    visit(T);
    PreOrder(T→lchild);
    PreOrder(T→rchild);
}
void InOrder(BiTree T){//中序
    if(T==NULL)return;
    InOrder(T→lchild);
    visit(T);
    InOrder(T→rchild);
}
void PostOrder(BiTree T){//后序
    if(T==NULL)return;
    PostOrder(T→lchild);
    PostOrder(T→rchild);
    visit(T);
}
借助栈非递归实现二叉树的先、中、后序遍历
void PreOrder(BiTree T){//先序
    Stack S;
    InitStack(S);
    BiTree p=T;//遍历指针
    while(p!=NULL||!isEmpty(S)){
        if(p){
            visit(p);
            Push(p)
            p=p→lchild;
        }else{
            Pop(S,p);
            p=p→rchild;
        }
    }
}

void InOrder(BiTree T){//中序
    Stack S;
    InitStack(S);
    BiTree p=T;//遍历指针
    while(p!=NULL||!isEmpty(S)){
        if(p){
            Push(p)
            p=p→lchild;
        }else{
            Pop(S,p);
            visit(p);
            p=p→rchild;
        }
    }
}

void PostOrder(BiTree T){//后序
    Stack S;
    InitStack(S);
    BiTree p;//遍历指针
    BTNode*r=NULL;//辅助指针,指向最近访问过的结点
    while(p!=NULL||!isEmpty(S)){
        if(p){
            Push(S,p);
            p=p→lchild;
        }else{
            GetTop(S,p);//读栈顶元素
            if(p→rchild!=NULL && p→rchild!=r){//右孩子不为空,且未被访问过
                p=p→rchild;
                Push(S,p);
                p=p→lchild;
            }else{
                Pop(S,p);
                visit(p);
                r=p;//记录最近访问过的结点
                p=NULL;//结点访问完后重置p指针
            }
        }
    }
}
●二叉树的自上而下自左至右的一般层次遍历(用队列的函数编写的非递归算法)
//递归实现
void LevelOrder(BiTree T){//非递归借助链队列实现
    if(T==NULL)return;
    LinkQueue Q;
    InitQueue(Q);
    BiTree p;
    EnQueue(Q,T);//根结点入队列
    while(!isEmpty(Q)){//队列不为空
        Dequeue(Q,p);//出队
        if(p→lchild!=NULL)EnQueue(Q,lchild);//左孩子入队
        if(p→rchild!=NULL)EnQueue(Q,rchild);//右孩子入队
    }
}
●二叉树的自下而上自右至左的层次遍历【栈的应用】

2、构建类题目

●已知二叉树的先序和中序序列,编写算法建立二叉树的二叉链链表(待补充)

3、判断类题目

●借助队列,二叉树以二叉链表存储,非递归判断一棵二叉树是否为完全二叉树(层次遍历的变形)
bool IsCompleteBiTree(BiTree T){
    if(T==NULL)return ture;
    bool flag=ture,ans=ture;
    LinkQueue Q;
    InitQueue(Q);
    BiTree p;
    EnQueue(Q,T);//根结点入队
    while(!isEmpty(Q)){
        DeQueue(Q,p);//出队
        if(p→lchild==NULL){//左孩子为空,右孩子不为空
            flag=false;
            if(p→rchild!=NULL){
                ans=flase;
            }
        }
        else {//左孩子不为空
            if(flag){//flag==Ture
                EnQueue(Q,p→lchild);//左孩子入栈
                if(p→rchild!=NULL)EnQueue(Q,p→rchild);
                else flag=false;
            }else ans=false;//左孩子的左孩子不为空但前面有叔叔为空
        }
    }
    return ans;
}
●二叉树以二叉链表形式存储,判断二叉树是否为二叉排序树(有点问题,仅供参考)
bool IsBST(BiTree *root,BTNode*left,BTNode*right){//一次遍历法
    if(root==NULL)return ture;
    if(left!=NULL&&root→data<=left→data)return false;
    if(right!=NULL&&root→data>right→data)return false;
    return IsBST(root→left,left,root)&&IsBST(root→right,root,right);
}
●二叉树以二叉链表形式存储,判断两棵二叉树是否同构(有待补充)

4、查找类题目

●递归实现二叉树中按值查找(有待补充)
●二叉树采用二叉链表存储结构,求先序遍历序列中第k个结点的值(有待补充)
求一般二叉树中两个结点的最近公共祖先(结点值均唯一)
/** * 二叉树最低公共祖先结点-自底向上解法 O(N) */
BTNode *btLCADown2Top(BTNode *root, BTNode *p, BTNode *q){
    if(!root)return NULL;
    if(root==p||root==q)return root;
    BTNode *left=btLCADown2Top(root->left,p,q);
    BTNode *right=btLCADown2Top(root->right,p,q);
    if(left!=NULL&&right!=NULL)
    return root;//如果p和q位于不同的子树
    return left!=NULL?left:right;//p和q在相同的子树,或者p和q不在子树中
}
求一棵给定节点至根节点的路径【栈的应用】
int flag=0;
void CherkNode(BiTree T,int target,Stack &S){
    if(T==NULL)return;
    if(flag==0)Push(S,T.data);
    if(T.data==target){
        flag=1;
        return;
    }
    CherkNode(T->lchild,target,Stack &S);
    CherkNode(T->rchild,target,Stack &S);
    if(flag==0)Pop(S);//清除非要寻找路径上的栈中元素
}

void findPath(BiTree T,int target){
    Stack S1,S2;
    InitStack(S1);
    InitStack(S2);
    CherkNode(T,target);
    BTNode*p;
    while(!isEmpty(S1)){
        Pop(S1,p);
        Push(S2,p);
    }
    while(!isEmpty(S2)){
        Pop(S2,p);
        visit(p);
    }
}

5距离类题目

●求一棵树的最大宽度(有待补充)
(1)层序遍历法
(2)先序遍历法
●求二叉树的叶结点的带权路径长度WPL(有待补充)

6、其他

●二叉链式存储的二叉树,交换每个结点的左右孩子/左右子树-即二叉树的镜像
void swapbitree(bitree &bt){//从下到上,递归实现
    if(bt==NULL)return;
    bitree *p;
    swapbitree(bt→lchild);//判不判断孩子是否存在均可
    swapbitree(bt→rchild);
    p=bt→lchild;
    bt→lchild=bt→rchild;
    bt→rchild=p;
}

void MirrorTree(BiTree &T){//从上到下,递归实现
    if(T==NULL)return;
    LNode *p=T→lchild;
    T→lchild=T→rchild;
    T→rchild=p;
    if(T→lchild!=NULL)MirrorTree(T→lchild);
    if(T→rchild!=NULL)MirrorTree(T→rchild)
}

(二)森林

●求孩子-兄弟表示法存储的森林的叶子结点数
typedef struct CSNode(){
    int data;
    struct CSNode*fch,*nsib;//孩子、兄弟
}CSNode,*CSTree;

int Leaves(CSTree T){
    if(T==NULL)return 0;
    if(T→fch==NULL)return 1+Leaves(T→nsib);//无左孩子为叶子结点,返回他和他兄弟的叶子结点总数
    else return Leaves(T→fch)+Leaves(T→nsib);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值