二叉树的相关操作

二叉树的相关操作

一:二叉树的构造,清空操作

/**
 * 前序递归构造二叉树
 * @param f
 * @param Tree
 * @return
 */
int CreatBinTree(BinTree*  Tree){
    char ch;
    scanf("%c",&ch);
    if (ch == ' '){
        *Tree = NULL;
    } else{
        (*Tree) = (BinTree)malloc(sizeof (BinNode));
        if (!(*Tree)){
            exit(0);
        }
        (*Tree)->data = ch;
        CreatBinTree(&(*Tree)->lchild);  //构造左子树
        CreatBinTree(&(*Tree)->rchild);  //构造右子树
    }
    return 1;
}



//清空二叉树
void ClearBiTree(BinTree *T){
    if (*T){    //如果当前结点不为空
        if (!(*T)->lchild){
            ClearBiTree((*T)->lchild);  //清空左子树
        } else if (!(*T)->rchild){
            ClearBiTree((*T)->rchild);  //清空右子树
        }
        free(*T);       //释放节点
        *T = NULL;
    }
}

二:二叉树的遍历

1、递归:

/**
 * 递归前序遍历
 * @param T
 */
void PreOrderTraverse(BinTree T){
    if (T){
        printf("%c\t",T->data);
        PreOrderTraverse(T->lchild);
        PreOrderTraverse(T->rchild);
    }

}

/**
 * 中序遍历二叉树
 * @param T
 */
void InorderTraverse(BinTree T){
    if (T){
        InorderTraverse(T->lchild);
        printf("%c\t",T->data);
        InorderTraverse(T->rchild);
    }
}

/**
 * 后续遍历二叉树
 * @param T
 */
void PostOrderTraverse(BinTree T){
    if (T){
        PostOrderTraverse(T->lchild);
        PostOrderTraverse(T->rchild);
        printf("%c\t",T->data);
    }
}

2、非递归

/**
 * 非递归前序遍历
 */
void PreOrder(BinTree T){
    //创建一个数组,用数组来模仿栈
    BinTree stack[15];
    int top = -1;   //栈顶指针
    BinTree p = T;
    while (p!=NULL || top!=-1){
        //当p不为空是将结点压入栈中
        if (p!=NULL){
            stack[++top] = p;
            printf("%c\t",p->data); //前序遍历在压入栈时候访问结点数据
            p = p->lchild;
        } else{ //当p为空,证明p的父结点没有左子树,则将p弹出访问右子树
            p = stack[top];
            top--;
            p = p->rchild;
        }
    }
}


/**
 * 非递归遍历二叉树
 * @param T
 */
void InOrder(BinTree T){
    BinTree stack[15];  //定义一个数组用来模拟栈的使用
    int top = -1;
    BinTree p = T;
    while (p!=NULL||top!=-1){
        if (p!=NULL){
            //将p结点压入栈
            stack[++top] = p;
            p = p->lchild;
        } else{
            p = stack[top--];
            printf("%c\t",p->data);
            p = p->rchild;
        }
    }
}


/**
 * 非递归后续遍历二叉树
 * @param T
 */
void PostOrder(BinTree T){
    BinTree stack[15];
    int flage[15];
    int top = -1;   //栈顶指针
    BinTree p = T;
    while (p!=NULL||top!=-1){
        if (p!=NULL){
            stack[++top] = p;
            flage[top] = 1;     //第一次访问,设个标志为1
            p = p->lchild;
        } else{
            if (flage[top] == 1){
                p = stack[top]; //获取栈顶元素,但是不取出
                flage[top] = 2; //标志这第二次访问
                p = p->rchild;  //访问右子树
            } else{ //第二次访问,证明也已经访问完了右子树,这时访问根节点
                p = stack[top--];
                printf("%c\t",p->data);
                p = NULL;   //置空,以便继续退栈,
            }
        }
    }
}

3、层次遍历

/**
 * 层次遍历二叉树
 * 层次遍历需要借助队列,先进先出,使用一个数组来模拟队列操作,循环队列
 * @param T
 */
void LevelTraverse(BinTree T){
    BinTree queue[15];
    int front = 0;
    int rear = 0;
    BinTree p = T;
    if (!T){
        return;
    } else{
        queue[rear] = p;
        rear = (rear+1)%15;
        while (rear!=front){    //当队列不为空时
            p = queue[front];
            printf("%c\t",p->data);
            front = (front+1)%15;   //元素出栈
            if (p->lchild!=NULL){
                //该结点的左孩子不为空
                queue[rear] = p->lchild;
                rear = (rear+1)%15;
            }
            if (p->rchild!=NULL){
                queue[rear] = p->rchild;
                rear = (rear+1)%15;
            }
        }
    }
}

三:寻找指定二叉树结点

1、递归查找

/**
 * 递归查找指定元素的结点
 * @param T
 * @param e
 * @return 返回当前元素的地址
 */
BinTree LocateNode(BinTree T,BinElemType e){
    BinTree p = NULL;
    if (T!=NULL){
        if (T->data == e){
            p = T;
        } else{
            if (p=LocateNode(T->lchild,e)){
                return p;
            }
            if (p=LocateNode(T->rchild,e)){
                return p;
            }
        }
    }
    return p;
}

3、非递归查找

/**
 * 非递归前序遍历查找在二叉树中给定数据的结点
 * @param T
 * @param e
 * @return
 */
BinTree  FindTreeNode(BinTree T,BinElemType e){
   //使用非递归前序遍历寻找
   BinTree stack[15];   //创建一个栈
   int top = -1;
   BinTree p = T;
    while (p!=NULL||top!=-1){
        if (p!=NULL){
            //判断是否相等
            if (p->data == e){
                return p;
            } else{
                stack[++top] = p;
                p = p->lchild;
            }
        } else{
            p = stack[top--];
            p = p->rchild;
        }
    }
    return NULL;
}

/**
 * 非递归后续遍历查找结点
 * @param e
 * @return
 */
BinTree PostFindTreeNode(BinTree T,BinElemType e){
    BinTree stack[15];
    int top = -1;
    int flage[15];
    BinTree p = T;
    while (p!=NULL||top!=-1){
        if (p!=NULL){
            stack[++top] = p;
            flage[top] = 1;
            p = p->lchild;
        } else{
            if (flage[top]!=2){
                //左子树为空,进行回退
                p = stack[top];
                flage[top] = 2;
                p = p->rchild;
            } else{
                p = stack[top--];
                if (e == p->data){
                    return p;
                } else{
                    p = NULL;
                }
            }
        }
    }
    return  NULL;
}

四:寻找父结点

1、递归查找

/**
 * 递归寻找指定节点的父结点
 * @param T 树
 * @param p 指定节点
 * @return 返回父结点地址
 */
BinNode* FatherRe(BinTree T,BinNode* p){
    BinNode* parent = NULL;
    if (T!=NULL){
        if (T->lchild == p||T->rchild == p){
            parent = T;
        } else{
            if (parent = FatherRe(T->lchild,p)){
                return parent;
            }
            if (parent = FatherRe(T->rchild,p)){
                return parent;
            }
        }
    }
    return parent;
}

2、非递归查找

/**
 * 非递归前序遍历查找给定节点的父结点
 * 相当于双指针
 * @param T
 * @param e
 * @return
 */
BinTree Parent(BinTree T,BinElemType e){
    BinTree stack[15];
    int top = -1;
    BinTree p = T;
    BinTree father;
    while (p!=NULL||top!=-1){
        if (p!=NULL){
            if (p->data == e){
                return father;
            }
            father = p;
            stack[++top] = p;
            p = p->lchild;

        } else{
            p = stack[top--];
            father = p;
            p = p->rchild;
        }
    }
    return NULL;
}

五:删除指定节点及其左右子树

/**
 * 删除结点及其左右子树
 * 寻找数据值为e的节点的父结点,令为p,待删结点为q结点,让父结点的指向为空,调用clear函数,将q所表示的子树删除。
 *
 * @param T
 * @param e
 * @return
 */
int DleteTreeNode(BinTree T,BinElemType e){
    BinTree p;
    BinTree parentTree = Parent(T,e);
    if ((parentTree->lchild)->data == e){
        p = parentTree->lchild;
        parentTree->lchild = NULL;
//        ClearBiTree(&p);
        return 1;
    } else if ((parentTree->rchild)->data == e){
        p = parentTree->rchild;
        parentTree->rchild = NULL;
//        ClearBiTree(&p);
        return 1;
    }
    return 0;
}

六:指定位置插入结点

/**
 * 在树T中的e结点之下插入一个新节点,并根据LR来决定插入的是右节点还是左节点
 * @param T     待插入的树
 * @param e     插入节点的父结点
 * @param newNode   插入的新节点
 * @param LR    判断是左节点还是右节点
 * @return      1表示插入成功,0表示插入失败
 * 思路:寻找数值为e的数据,并根据LR来决定插入的是做还是右子树,并用一个指针p来表示当前值为e的左或右节点,
 * 然后执行插入
 */
int InsertNode(BinTree T,BinElemType e,BinNode* newNode,char LR){
    BinTree parent = LocateNode(T,e);
    if (T==NULL||parent==NULL){
        return 0;
    }
    BinTree p = NULL;
    if (LR=='L'){
        p = parent->lchild;
        parent->lchild = newNode;
        newNode->lchild = p;
    } else if ('R'){
        p = parent->rchild;
        parent->rchild = newNode;
        newNode->rchild = p;
    }
    return 1;
}

七:求二叉树第k层的节点数

1、递归

/**
 * 递归求第k层的节点数
 * @param T
 * @param kLevel
 * @return
 */
int GetKLevelNum(BinTree T,int kLevel){
    if(T==NULL||kLevel<=0){
        return 0;
    }
    if (T!=NULL&&kLevel == 1){
        return 1;
    }
    return (GetKLevelNum(T->lchild,kLevel-1) + GetKLevelNum(T->rchild,kLevel-1));
}

2、非递归

kong

八:深拷贝二叉树

/**复制二叉树
//递归后续遍历递归复制二叉树
*/
 BinTree CopyTreePre(BinTree T){
    if (T==NULL){
        return NULL;
    }
    BinTree lchild = CopyTreePre(T->lchild);
    BinTree rchild = CopyTreePre(T->rchild);

    //创建一个根节点
    BinTree newNode = malloc(sizeof (BinNode));
    newNode ->data = T->data;
    newNode ->lchild = lchild;
    newNode->rchild = rchild;
    return newNode;
}

九:求二叉树的深度

/**
 * 求树的深度
 * @param T
 * @return
 */
int BiTreeDepth(BinTree T){
    int LD,RD;  //计算左右子树的深度
    if (T == NULL){
        return 0;
    }
    LD =BiTreeDepth(T->lchild);
    RD = BiTreeDepth(T->rchild);
    return (LD>=RD?LD:RD)+1;
}

十:计算二叉树的结点数

1、递归

/**
 * 递归计算树中结点的个数
 * @param T
 * @return
 */
int CountNode(BinTree T){
    if (T ==NULL){
        return 0;
    }
    return CountNode(T->lchild)+CountNode(T->rchild)+1;
}

2、非递归

/**
 * 非递归前序遍历统计二叉树结点的个数
 * @param T
 * @return
 */
int CountNodePre(BinTree T){
    int number = 0;
    BinTree stack[15];
    int top = -1;
    BinTree p = T;
    while (p!=NULL||top!=-1){
        if (p!=NULL){
            //将结点压入栈
            stack[++top] = p;
            number++;
            p = p->lchild;
        } else{
            p = stack[top--];
            p = p->rchild;
        }
    }
    return number;
}

十一:统计二叉树中叶子节点的数量

1、递归

/**
 * 递归求二叉树叶子节点的数量
 * @param T
 * @return
 */
int CountLeaf(BinTree T){
    if (T == NULL){
        return 0;
    }
    if (!T->lchild&&!T->rchild){    //如果当前节点的左右孩子节点都为空,那么返回一
        return 1;
    }
    return CountLeaf(T->lchild)+CountLeaf(T->rchild);
}

十二:判断两棵树的结构是否相同

/**
 * 判断两棵树的结构是否相同
 * 结构相同即指两棵树的外形相同,而与树节点中表示的数据多少无关
 * @param T1
 * @param T2
 * @return
 */
bool StructureTree(BinTree T1,BinTree T2){
    if (T1 == NULL && T2 == NULL){
        return true;
    } else if (T1 == NULL || T2 == NULL){
        return false;
    }
    return StructureTree(T1->lchild,T2->lchild) && StructureTree(T1->rchild,T2->rchild);
}

十三:求一棵树的镜像树

/**
 * 求二叉树的镜像树
 * 使用递归
 * @param T
 */
void Mirror(BinTree T){
    if (T == NULL){
        return;
    }
    //进行翻转
    BinTree p = NULL;
    p = T->rchild;
    T->rchild = T->lchild;
    T->lchild = p;
    //递归
    Mirror(T->lchild);
    Mirror(T->rchild);
}

十四:获取某节点所在的层数

/**
 * 获取某节点所在的层数
 * @param T
 * @param target
 * @param level 表示当前所在的层数,初始值为1
 * @return
 */
int GetNodeLevel(BinTree T,BinNode* target,int level){
    int levelnum;
    if (T!=NULL){
        if (T == target){
            return level;
        }
        levelnum = GetNodeLevel(T->lchild,target,level+1);
        if (levelnum != -1){    //表示已经查到
            return levelnum;
        } else{
            return GetNodeLevel(T->rchild,target,level+1);
        }
    }
    return -1;
}
/**
 * 获取层数函数的入口函数
 * 当前算法中的层数是从1开始的,即根节点是第一层。吉大课本上为0,注意区分
 * @param T
 * @param target
 * @return
 */
int NodeLevel(BinTree T,BinNode* target){
    if (T!=NULL){
        return GetNodeLevel(T,target,1);
    }
    return -1;
}

十五:求两个结点的最低公共祖先结点

1、非递归

/**
 * 非递归
 * 求两个结点的最低公共祖先节点的
 * 思路:
 *      两个结点有两种情况,
 *          在同一层;
 *              同一个结点
 *              不同结点
 *
 *          不在同一层;
 *              高层不动,先获得低层的父结点,转换成在同一层的情况
 * @param node1
 * @param node2
 * @return
 */
BinTree FindLCA1(BinTree T,BinNode* node1,BinNode* node2){

    //不在同一层
    BinTree parent1 = node1;
    BinTree parent2 = node2;
    while (NodeLevel(T,parent1)>NodeLevel(T,parent2)){
       parent1 = FatherRe(T,parent1);
    }
    while (NodeLevel(T,parent1)<NodeLevel(T,parent2)){
        parent2 = FatherRe(T,parent2);
    }
    //在同一层
    if (parent1 == parent2){    //node1和node2就是同一个结点,或者node1(node2)是node2(node1)的父结点
        return parent1;
    } else{
        do {
           parent1 = FatherRe(T,parent1);
           parent2 = FatherRe(T,parent2);
        } while (parent1!=parent2);
        return parent1;
    }
}

2、递归

/**
 * 递归求两个结点的最低公共结点
 * @param T
 * @param node1
 * @param node2
 * @return
 */
BinTree FindLCA2(BinTree T,BinNode* node1,BinNode* node2){
    if (T == NULL){
        return NULL;
    }
    if (T == node1||T == node2){
        return T;
    }
    BinTree left = FindLCA2(T->lchild,node1,node2);
    BinTree right = FindLCA2(T->rchild,node1,node2);
    if (left&&right){
        return T;
    }
    return left?left:right;
}

十六:求任意两个节点之间的距离

/**
 * 两节点之间的距离
 * 思路:
 *      找到两个节点的最低公共节点
 *      两个结点之间的距离 = 结点一到公共父结点的距离+结点二到公共父节点之间的距离
 *      结点到公共父结点之间的距离=结点的层数 - 公共父结点的层数
 * @param T
 * @param node1
 * @param node2
 * @return
 */
int DistenceNodes(BinTree T,BinNode* node1,BinNode* node2){
    if (node2 == node1){
        return 0;
    }
    BinTree father = FindLCA2(T,node1,node2);
    int fatherLevel = NodeLevel(T,father);
    int node1Level = NodeLevel(T,node1);
    int node2Level = NodeLevel(T,node2);
    int disNode1 = node1Level - fatherLevel;
    int disNode2 = node2Level - fatherLevel;
    return disNode1 + disNode2;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值