17. 二叉树的建立与基本操作

1 问题

编写程序实现二叉树的如下操作:
1) 建立二叉链表
2) 二叉树的先序、中序、后序遍历
3) 求二叉树的叶子结点个数
4) 将二叉树中所有结点的左、右子树相互交换

输入:
  扩展二叉树先序序列:ab#d##ce###。其中#代表空指针。

输出:
  二叉树的凹入表示
  二叉树的先序序列、中序序列、后序序列
  二叉树叶子结点个数
  左、右子树相互交换后的二叉树的凹入表示
  左、右子树相互交换后的二叉树的先序序列、中序序列、后序序列。

说明:
  在输出凹入表示的二叉树时,先输出根结点,然后依次输出左右子树,上下层结点之间相隔 3 个空格。

 测试输入 期待的输出 时间限制 内存限制 额外进程
测试用例 1以文本方式显示
  1. ab#d##ce###↵
以文本方式显示
  1. BiTree↵
  2. a↵
  3.     b↵
  4.         d↵
  5.     c↵
  6.         e↵
  7. pre_sequence  : abdce↵
  8. in_sequence   : bdaec↵
  9. post_sequence : dbeca↵
  10. Number of leaf: 2↵
  11. BiTree swapped↵
  12. a↵
  13.     c↵
  14.         e↵
  15.     b↵
  16.         d↵
  17. pre_sequence  : acebd↵
  18. in_sequence   : ceadb↵
  19. post_sequence : ecdba↵
1秒64M0
测试用例 2以文本方式显示
  1. abd##e##cf##g##↵
以文本方式显示
  1. BiTree↵
  2. a↵
  3.     b↵
  4.         d↵
  5.         e↵
  6.     c↵
  7.         f↵
  8.         g↵
  9. pre_sequence  : abdecfg↵
  10. in_sequence   : dbeafcg↵
  11. post_sequence : debfgca↵
  12. Number of leaf: 4↵
  13. BiTree swapped↵
  14. a↵
  15.     c↵
  16.         g↵
  17.         f↵
  18.     b↵
  19.         e↵
  20.         d↵
  21. pre_sequence  : acgfbed↵
  22. in_sequence   : gcfaebd↵
  23. post_sequence : gfcedba↵
1秒64M0

2 解题

  • 属于基础操作,着重理解其中的递归过程和利用二级指针创建二叉树的操作
#include <cstdio>
#include <cstdlib>
#include <iomanip>  //cout函数格式化输出头文件
#include <iostream>

using namespace std;

typedef struct BiNode {
    char element;
    struct BiNode *left;
    struct BiNode *right;
} * BiTree;

int numleaf = 0;  //叶子节点的数量

// 使用二级指针递归创建二叉树(不需要返回)
void linkcreat(BiTree *rt) {
    char ch;
    cin >> ch;
    if (ch == '#')
        *rt = NULL;
    else {
        *rt = (BiTree)malloc(sizeof(struct BiNode));
        (*rt)->element = ch;
        linkcreat(&(*rt)->left);
        linkcreat(&(*rt)->right);
        if (!(*rt)->left && !(*rt)->right) numleaf++;
    }
}

// 使用返回值递归创建二叉树
BiTree linkcreat(BiTree rt) {
    char ch;
    cin >> ch;
    if (ch == '#')
        rt = NULL;
    else {
        rt = (BiTree)malloc(sizeof(struct BiNode));
        rt->left = NULL;
        rt->right = NULL;
        rt->element = ch;
        rt->left = linkcreat(rt->left);
        rt->right = linkcreat(rt->right);
        if (!rt->left && !rt->right) numleaf++;
    }
    return rt;
}


void formatprint(char ch, int num) {
    for (int i = 0; i < 4 * num; i++) cout << " ";
    cout << ch << endl;
}

void listprint(BiTree rt, int depth) {  //depth是深度,用来控制凹入法的格式化输出
    if (rt) {   //非空
        formatprint(rt->element, depth++);  //这一行执行完了以后depth的值才回增加
        listprint(rt->left, depth);
        listprint(rt->right, depth);
    }
}

void preorder(BiTree rt) {
    if (rt) {
        cout << rt->element;
        preorder(rt->left);
        preorder(rt->right);
    }
}

void inorder(BiTree rt) {
    if (rt) {
        inorder(rt->left);
        cout << rt->element;
        inorder(rt->right);
    }
}

void postorder(BiTree rt) {
    if (rt) {
        postorder(rt->left);
        postorder(rt->right);
        cout << rt->element;
    }
}

void Swaptree(BiTree rt) {
    if (rt) {
        if (rt->left || rt->right) {
            BiTree tmp;         //直接交换地址
            tmp = rt->left;
            rt->left = rt->right;
            rt->right = tmp;
        }
        Swaptree(rt->left);
        Swaptree(rt->right);
    }
}

int main() {
    //freopen("file in.txt", "r", stdin);
    BiTree root;
    root = NULL;    //初始化

    // linkcreat(&root);
    root = linkcreat(root);
    cout << "BiTree" << endl;
    listprint(root, 0); //初始深度为0

    // 默认是右对齐,这里left控制左对齐,宽度14
    cout << left << setw(14) << "pre_sequence";
    cout << ": ";
    preorder(root);
    cout << endl;
    cout << left << setw(14) << "in_sequence";
    cout << ": ";
    inorder(root);
    cout << endl;
    cout << left << setw(14) << "post_sequence";
    cout << ": ";
    postorder(root);
    cout << endl;

    cout << left << setw(14) << "Number of leaf";
    cout << ": ";
    cout << numleaf << endl;

    Swaptree(root);
    cout << left << setw(14) << "BiTree swapped";
    cout << endl;
    listprint(root, 0);

    cout << left << setw(14) << "pre_sequence";
    cout << ": ";
    preorder(root);
    cout << endl;
    cout << left << setw(14) << "in_sequence";
    cout << ": ";
    inorder(root);
    cout << endl;
    cout << left << setw(14) << "post_sequence";
    cout << ": ";
    postorder(root);
    cout << endl;

    return 0;
}

小结

  • 自定义函数可以名字相同,参数不同,调用的时候主函数根据参数类型自行调用相关的函数,代码中就包含了两个listcreat函数
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值