数据结构二叉树实验报告

第一个实验是求一颗树的结点个数,叶子结点个数,某一个结点的深度,以及整颗树的宽度.
先来考虑一下如何读入一颗树.其实递归的读入左右子树即可.
参考代码:
树的结构体:

struct Tree{
    
    
    char data;
    Tree * lson,* rson;
};

读入部分

bool input(Tree *now){
    
     // 这部分只是读入这颗树,不一定要这么写
    cin >> now->data;
    if(now->data == '0') return false; // 空节点就用'0'来识别返回false
    now->lson = new Tree;
    now->rson = new Tree;
    if(!input(now->lson)) now->lson = NULL; // 空节点
    if(!input(now->rson)) now->rson = NULL; // 空节点
    return true;
}

前两个很好求,深度和宽度我们用两个数组dep和wid来记录一下(因为树上结点权值是互异的,这样做比较方便).代码里的注释写的应该比较清楚了.

int num,lefnum;
int wid[100],dep[100],l=0,r=0;
void bfs(Tree *root){
    
     // 根节点
    queue<Tree*> q;
    dep[root->data] = 1; // 初始化根节点的深度为1
    wid[root->data] = 0; // 初始化跟节点的宽度为0
    q.push(root);
    while(q.size()){
    
    
        Tree *cur = q.front();
        q.pop();
        num++; // 结点数量
        if(cur->lson != NULL){
    
    
            q.push(cur->lson);
            dep[cur->lson->data] = dep[cur->data] + 1; // 深度是父亲节点的深度+1
            wid[cur->lson->data] = wid[cur->data] - 1; // 左边的宽度是父亲节点的宽度-1.
            l = min(l,wid[cur->lson->data]); // 记录一下遍历时候得到的最大和最小宽度.
            r = max(r,wid[cur->lson->data]); // // 记录一下遍历时候得到的最大和最小宽度.
        }
        if(cur->rson != NULL){
    
    
            q.push(cur->rson);
            dep[cur->rson->data] = dep[cur->data] + 1; // 深度是父亲节点的深度+1
            wid[cur->rson->data] = wid[cur->data] + 1; // 右边的宽度是父亲节点的宽度+1.
            l = min(l,wid[cur->rson->data]); // 记录一下遍历时候得到的最大和最小宽度.
            r = max(r,wid[cur->rson->data]); // 记录一下遍历时候得到的最大和最小宽度.
        }
        if(cur->lson == NULL && cur->rson == NULL) lefnum++; // 左右节点都是空说明是叶子节点.
    }
}

第二个实验是给一颗表达式树.求运算的结果.
如果当前结点是字符,需要先计算出左右结点的结果把这个结果return回去,如果是数字,直接return这个数字.
代码(读入部分和上面是一样的,只不过终止字符可以用其他没出现的字符来判断).

double dfs(Tree *now){
    
     // 这部分是对建好的树进行遍历.
    if(now == NULL) return 0;
    if(isdigit(now->data)) return now->data-'0'; // 如果是数字的话,直接返回即可.
    char op = now->data;
    double lres = dfs(now->lson),rres = dfs(now->rson); // 如果是符号,我们需要知道左右子树的运算结果后再来计算当前节点的结果.
    if(op == '-') return lres - rres; // 判断运算符号.
    if(op == '+') return lres + rres;
    if(op == '*') return lres * rres;
    return lres / rres;
}

第三个实验比较有意思,由于懒得想一个时间复杂度优秀的算法,就直接暴力乱搞了.
只需要枚举b1树的每一个起点,然后看是否和b2结构相同即可.
参考代码

bool check_same(Tree *a,Tree *b){
    
    
    if(a == NULL && b != NULL) return false; // 只有一个是空树说明不相同.
    if(a != NULL && b == NULL) return false;
    if(a == NULL && b == NULL) return true; // 都是空树说明相同
    return (check_same(a->lson,b->lson) && check_same(a->rson,b->rson)); // 左右子树同时相同才相同
}
bool dfs(Tree *a,Tree *b){
    
     // b保证不是空树
    if(a == NULL) return false;
    if(check_same(a,b)) return true; // 枚举每一个起点.
    return (dfs(a->lson,b) || dfs(a->rson,b)); // 只要有一个就够了.
}

猜你喜欢

转载自blog.csdn.net/weixin_45590210/article/details/109958391