二叉树相关算法的实现

本文介绍了二叉树的链式存储结构,并提供了从顺序存储结构生成二叉树的算法。同时,展示了如何统计二叉树中度为1、2、0的结点个数,计算树的高度和宽度,删除叶节点,查找结点位置,获取最大元素以及交换结点子女。此外,还给出了以先序次序输出结点数据和层次的方法。
摘要由CSDN通过智能技术生成

二叉树的链式存储结构

typedef struct BinTr{
    int data; // 数据域
    struct BinTr *left, *right; // 左右指针域
    // int loc; // 附加:记录结点所在的层号
}*BinTree, BinNode;

取最大值max函数的实现

int max(int a, int b){
    return a > b ? a : b;
}

0.由二叉树的顺序存储结构序列生成二叉树(的链式存储结构)

给定二叉树的顺序存储结构,结构中每个元素代表二叉树中结点的数据;
存储从下标idx为1的位置开始,其中下标为2 * idx存储的是idx结点的左孩子,2 * idx+1存储idx结点的右孩子,0为NULL;用该序列来生成二叉树(的链式存储)。

int createSeq[] = {-1, 1, 2, 3, 0, 4, 0, 5, 0, 0, 6, 0};
BinTree bt = createBinTree(createSeq, sizeof(createSeq) / sizeof(createSeq[0]), 1);
BinTree createBinTree(int createSeq[], int size, int u){
    if(u >= size || createSeq[u] == 0) return NULL;
    BinNode* node = (BinNode* )malloc(sizeof(BinNode));
    node -> data = createSeq[u];
    node -> left = createBinTree(createSeq, size, u * 2);
    node -> right = createBinTree(createSeq, size, u * 2 + 1);
    return node;
}

1.统计二叉树中度为1、2、0的结点个数

// 1.统计二叉树中度为1的结点个数
int countDegree1(BinTree u){
    if(u == NULL) return 0;
    return countDegree1(u -> left) + countDegree1(u -> right) + 
    (u -> left && u -> right == NULL || u -> left == NULL && u -> right);
}

// 2.统计二叉树中度为2的结点个数
int countDegree2(BinTree u){
    if(u == NULL) return 0;
    return countDegree2(u -> left) + countDegree2(u -> right) + (u -> left && u -> right);
}

// 3.统计二叉树中度为0的结点个数
int countDegree0(BinTree u){
    if(u == NULL) return 0;
    return countDegree0(u -> left) + countDegree0(u -> right) + (u -> left == NULL && u -> right == NULL);
}

2.求得二叉树的高度

int getHeight(BinTree u){
    if(u == NULL) return 0;
    return max(getHeight(u -> left), getHeight(u -> right)) + 1;
}

3.求得二叉树的宽度

二叉树的宽度是指含有最多节点数的对应层对应的节点数
方式:
在结构体属性中附加一个层数loc属性,用于记录每个结点对应的层数(也可以采用哈希的方式进行存储),
对二叉树进行层次遍历(需要使用队列),根结点所在的是第一层,由根结点拓展出来的是第二层,将这些结点入队;
由根结点的子节点拓展出来的是第三层,将这些结点入队,以此类推;
所以出队列时的各结点元素的层数号必定以1223…34…4这种非严格递增的顺序排列,
那么树的宽度就是出队所形成的层数号序列中的最长的重复数字序列的长度,
可以用临时变量cnt来存储某个层号下的结点个数(重复数字的个数),若出队的层号发生改变,
说明先前层号下的结点全部出队,那么将其与res(结果值)去max即可,
直至所有结点出列为止。

int getWidth(BinTree u){
    BinNode* queue[105];
    int head = 0, tail = 0;
    u -> loc = 1;
    int res = 1, cnt = 0, cur = 1;
    queue[tail ++] = u;
    while(head != tail){ // 队列不空
        BinNode* t = queue[head ++];
        if(t -> left){
            queue[tail ++] = t -> left;
            t -> left -> loc = t -> loc + 1; // 父结点层号更新子结点层号
            cnt ++;
        }if(t -> right){
            queue[tail ++] = t -> right;
            t -> right -> loc = t -> loc + 1; // 父结点层号更新子结点层号
            cnt ++;
        }
        if(head != tail && queue[head] -> loc != cur){ // 层号发生变动
            res = max(res, cnt);
            cur = queue[head] -> loc;
            cnt = 0;
        }
    }
    return res;
}

4.从二叉树中删除所有叶节点

void delLeaves(BinTree u){
    if(u -> left){
        // u的左孩子是叶子结点
        if(u -> left -> left == NULL && u -> left -> right == NULL){
            BinNode* tmp = u -> left;
            u -> left = NULL;
            free(tmp);
        }else
            delLeaves(u -> left);
    }
    if(u -> right){
        // u的右孩子是叶子结点
        if(u -> right -> left == NULL && u -> right -> right == NULL){
            BinNode* tmp = u -> right;
            u -> right = NULL;
            free(tmp);
        }else
            delLeaves(u -> right);
    }
}

5.计算指定结点*p所在的层次(为易于验证正确性,这里只查看结点的数据域,因此结点的数据要保证互不相同)

// tag:所要搜寻到的目标结点, cur: 当前所在层数, 结果由res带回, res为-1表示没有找到
void getLoc(BinTree u, BinNode* tag, int cur, int *res){
    if(*res != -1 || u == NULL) return;
    if(u -> data == tag -> data){
        *res = cur;
        return;
    }
    getLoc(u -> left, tag, cur + 1, res);
    getLoc(u -> right, tag, cur + 1, res);
}

6.计算二叉树中各结点的最大元素的值

int getMax(BinTree u){
    int res = u -> data;
    if(u -> left)
        res = max(res, getMax(u -> left));
    if(u -> right)
        res = max(res, getMax(u -> right));
    return res;
}

7.交换二叉树中每个结点的两个子女

void changeChild(BinTree u){
    if(u == NULL) return;
    changeChild(u -> left);
    changeChild(u -> right);
    BinNode* t = u -> left;
    u -> left = u -> right;
    u -> right = t;
}

8.以先序次序输出一颗二叉树中所有结点的数据值及结点所在的层次

void preOrder(BinTree u, int loc){
    if(u == NULL) return;
    printf("%d %d\n", u -> data, loc);
    preOrder(u -> left, loc + 1);
    preOrder(u -> right, loc + 1);
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值