【数据结构-树】二叉树的相关算法

1 计算二叉树中双分支结点的个数

假设二叉树采用二叉链表存储,试设计一个算法,计算一棵给定二叉树的所有双分支结点个数。

int count = 0;

void Degree2 (BiTree T){
    if (T != NULL){
        Degree2(T->lchild);
        Degree2(T->rchild);
        if ((T->lchild != NULL) && (T->rchild != NULL))
            count++;   
    }
} 

2 交换二叉树中所有左右子树

编写一个把树 B 中所有结点的左、右子树进行交换的函数。

void SwapNodeChild (BiTree T){
    if (T->lchild != NULL)
        SwapNodeChild(T->lchild);
    if (T->rchild != NULL)
        SwapNodeChild(T->rchild);

    Swap(T->lchild, T->rchild);
}

3 求先序遍历第 k 个元素

设计一个算法,求先序遍历序列中第 k 个结点的值。

int i = 1;

int PreOrder (BiTree T, int k){
    if (T != NULL){
        if (i == k)
            return T->data;
        i++;
        
        PreOrder(T->lchild, k);
        PreOrder(T->rchild, k);
    }
}

4 删去值为 x 的子树

对于树中每个元素值为 x 的结点,删去以它为根的子树,并释放相应的空间。

void Delete (BiTree T){ // 找到元素值为 x 的结点后,递归删去它的左子树和右子树
    if (T != NULL){
        Delete(T->lchild);
        Delete(T->rchild);
        free(T);
    }
}

void Find (BiTree T, int x){
    if (T != NULL){
        if (T->data == x){ // 若找到元素值为 x 的结点
            Delete(T);     // 开始递归删去它的左子树和右子树
            return;
        }
        else{ // 若不是元素值为 x 的结点
            Find(T->lchild, x); // 继续找左子树中有无元素值为 x 的结点
            Find(T->rchild, x); // 继续找右子树中有无元素值为 x 的结点
        }
    }
}

5 计算二叉树的带权路径长度(WPL)

二叉树的带权路径长度(WPL)是二叉树中所有叶结点的带权路径长度之和。给定一棵二叉树 T,采用二叉链表存储结点结构为

leftweightright
左子树指针域权值右子树指针域

其中叶结点的 weight 域保存该结点的非负权值,设 root 为指向 T 的根结点的指针,请设计求 T 的 WPL 的算法。

算法的核心思想是先序遍历 + 计算层数,代码如下:

int WPL;

void WPL_PreOrder (BiTree T, int level){
    if (T != NULL){
        if ((T->lchild != NULL) && (T->rchild != NULL))
            WPL = WPL + T->weight * level;
        else if ((T->lchild != NULL) && (T->rchild == NULL))
            WPL_PreOrder(T->lchild, level + 1);
        else
            WPL_PreOrder(T->rchild, level + 1);
    }
}

// main 函数中调用:
WPL_PreOrder(Tree, 0);

6 将表达式树转化为等价的中缀表达式

请设计一个算法,将给定的表达式树,转换成等价的中缀表达式并输出。

二叉树结点定义如下:

typedef struct node{
    char data[10];
    struct node *left, * right;
} BTree;

算法的核心思想是中序遍历 + 计算层数。可以先将中序遍历的表达式先写出来,再与加了括号的表达式对比一下,看看哪个地方加了括号。遍历左子树前加上左括号,遍历完右子树后加上右括号,根结点(表达式最外层)和叶结点(操作数)不需要加括号。代码如下:

void InOrder (BTree *T, int level){
    if (T != NULL){
        if ((T->left == NULL) && (T->right == NULL)) // 叶结点
            输出 T->data; // 输出操作数
        else{
            if (level > 1) // 若有子表达式则加 1 层括号
                输出 "(";
            InOrder(T->left, level + 1);
            输出 T->data; // 输出操作符
            InOrder(T->right, level + 1);
            if (level > 1) // 若有子表达式则加 1 层括号
                输出 ")";
        }
    }
}

// main 函数中调用:
InOrder(Tree, 0);

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值