完全二叉树的各种操作

//
// Created by Cauchyshy on 2023/5/30.
//
#include <cstdio>
#include <iostream>
#include <malloc.h>

using namespace std;

struct treeNode {
    int a; // 数据成员
    struct treeNode *pFather; // 父节点
    struct treeNode *pLeft; // 左孩子
    struct treeNode *pRight; // 右孩子
};

struct queue {
    struct treeNode *tree;
    struct queue *next;
};

struct treeNode* createTree(int *arr, int len) {
    if (NULL == arr || len <= 0)
        return NULL;
    // 申请节点
    struct treeNode* root = (struct treeNode*)malloc(sizeof(struct treeNode) * len);
    if (NULL == root) {
        return NULL;
    }
    // 赋初值
    for (int i = 0; i < len; ++i) {
        root[i].a = arr[i];
        root[i].pFather = NULL;
        root[i].pLeft = NULL;
        root[i].pRight = NULL;
    }
    // 树节点连接
    for (int i = 0; 2 * i + 1 < len; ++i) {
        root[i].pLeft = &root[2 * i + 1]; // 左节点赋值
        root[2 * i + 1].pFather = &root[i];
        if (2 * i + 2  < len) {
            root[i].pRight = &root[2 * i + 2]; // 右节点
            root[2 * i + 2].pFather = &root[i];
        }
    }
    // 返回树根
    return root;
}

// 入队函数
void push(struct queue** queueHead, struct queue** queueTail, struct treeNode* node) {
    if (node == NULL) {
        return ;
    }
    // 申请节点
    struct queue* tp = (struct queue*)malloc(sizeof(struct queue));
    if (tp == NULL) {
        return ;
    }
    // 节点赋值
    tp->tree = node;
    tp->next = NULL;
    // 连接
    // 队列为空 既是头也是尾
    if (NULL == *queueHead) {
        *queueHead = tp;
       // *queueTail = tp;
    } else {
        (*queueTail)->next = tp;
       // *queueTail = tp;
    }
    *queueTail = tp;
}

// 出队 头删
struct treeNode * pop(struct queue** queueHead, struct queue** queueTail) {
    if (*queueHead == NULL || *queueTail == NULL) {
        return NULL;
    }
    // 记录头
    struct queue *tp = *queueHead;
    // 头想象走一个节点
    (*queueHead) = (*queueHead)->next;
    // 释放刚才的节点
    struct treeNode *res = tp->tree;
    free(tp);
    // 刚好一个节点 往下走就是空了
    if (NULL == *queueHead) { // 队列放空
        *queueHead = NULL;
        *queueTail = NULL;
    }

    return res;
}

// 层序遍历
void look(struct queue** queueHead, struct queue** queueTail, struct treeNode *root) {
    if (NULL == root) {
        return ;
    }
    push(queueHead, queueTail, root); // 根入队
    while (1) {
        struct treeNode* tp = pop(queueHead, queueTail);
        printf("%d ", tp->a);
        if (tp->pLeft != NULL)
            push(queueHead, queueTail, tp->pLeft);
        if (tp->pRight != NULL)
            push(queueHead, queueTail, tp->pRight);
        if (*queueHead == NULL)
            break;
    }
}

// 修改指定节点
void modify(struct queue** queueHead, struct queue** queueTail, struct treeNode *root, int oldVal, int newVal) {
    if (NULL == root) {
        return ;
    }
    push(queueHead, queueTail, root); // 根入队
    while (1) {
        struct treeNode* tp = pop(queueHead, queueTail);
        // printf("%d ", tp->a);
        if (oldVal == tp->a)
            tp->a = newVal; // 找到后修改
        if (tp->pLeft != NULL)
            push(queueHead, queueTail, tp->pLeft);
        if (tp->pRight != NULL)
            push(queueHead, queueTail, tp->pRight);
        if (*queueHead == NULL)
            break;
    }
}

// 清空队列
void clearQueue(struct queue** queueHead, struct queue** queueTail) {
    while (pop(queueHead, queueTail));
}

// 添加一个节点
void insert(struct queue** queueHead, struct queue** queueTail, struct treeNode **root, int data) {
    if (NULL == root) {
        return ;
    }
    // 空树, 节点即为根
    if (NULL == *root) {
        // 申请节点
        struct treeNode *tp = (struct treeNode *) malloc(sizeof(struct treeNode));
        if (NULL == tp)
            return ;
        // 节点成员赋值
        tp->a = data;
        tp->pLeft = NULL;
        tp->pRight = NULL;
        tp->pFather = NULL;
        // 设置为树根
        *root = tp;
        return ;
    }
    push(queueHead, queueTail, *root);
    while (1) {
        struct treeNode *tp = pop(queueHead, queueTail);
        if (NULL == tp->pLeft) {
            // 添加到左子树
            // 创建节点
            struct treeNode *temp = (struct treeNode*)malloc(sizeof(struct treeNode));
            if (NULL == temp) {
                return ;
            }
            // 成员赋值
            temp->a = data;
            temp->pFather = NULL;
            temp->pLeft = NULL;
            temp->pRight = NULL;
            // 连接
            tp->pLeft = temp;
            temp->pFather = tp;
            // 清空队列 防止残留
            clearQueue(queueHead, queueTail);
            break; // return ;
        }

        if (NULL == tp->pRight) {
            // 添加到右子树上
            // 创建节点
            struct treeNode *temp = (struct treeNode*)malloc(sizeof(struct treeNode));
            if (NULL == temp) {
                return ;
            }
            // 成员赋值
            temp->a = data;
            temp->pFather = NULL;
            temp->pLeft = NULL;
            temp->pRight = NULL;
            // 连接
            tp->pRight = temp;
            temp->pFather = tp;
            // 清空队列 防止残留
            clearQueue(queueHead, queueTail);
            break; // return ;
        }

        if (NULL != tp->pLeft) {
            push(queueHead, queueTail, tp->pLeft);
        }
        if (NULL != tp->pRight) {
            push(queueHead, queueTail, tp->pRight);
        }

    }
}

// 删除 这里不进行删除指定元素 因为会破坏完全二叉树的结构
void freeTree(int cn, struct queue** queueHead, struct queue** queueTail, struct treeNode **root) {
    if (NULL == root || NULL == *root) {
        return ;
    }
    push(queueHead, queueTail, *root);
    int cnt = 0;
    while (1) {
        struct treeNode *tp = pop(queueHead, queueTail);
        cnt++;
        if (tp->pLeft != NULL)
            push(queueHead, queueTail, tp->pLeft);
        if (tp->pRight != NULL)
            push(queueHead, queueTail, tp->pRight);
         if (cnt > cn) // cnt > len 因为是个数组
            free(tp);
        if (NULL == *queueTail)
            break;
    }
    // 树置为空
    if (cn != 0)
        free(*root);
    *root = NULL;
}

// 删除最后一个节点
void deleteCreate(int cn, struct queue **head, struct queue **tail, struct treeNode** root) {
    if (NULL == root || NULL == *root)
        return ;
    push(head, tail, *root);
    struct treeNode *tp = NULL;
    int pos = 0;
    while (1) {
        tp = pop(head, tail);
        pos++;
        if (tp->pLeft != NULL) {
            push(head, tail, tp->pLeft);
        }
        if (tp->pRight != NULL) {
            push(head, tail, tp->pRight);
        }
        if (NULL == *head)
            break;
    }
    // 做完了之后tp就是完全二叉树的最后一个节点
    if (tp->pFather == NULL) {
        // tp为根
        free(tp);
        *root = NULL;
        return ;
    }
    if (tp == (tp->pFather->pLeft)) {
        // 为父指针的左子树
        tp->pFather->pLeft = NULL;
        if (pos > cn)
            free(tp);
        return ;
    }
    if (tp == (tp->pFather->pRight)) {
        tp->pFather->pRight = NULL;
        if (pos > cn)
           free(tp);
        return ;
    }

}

int main() {
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int cnt = 0;
    cnt = sizeof(arr) / (sizeof(arr[0]));
    // int arr[] = {};
    // struct treeNode *root = createTree(arr, 10);
    struct treeNode *root = createTree(arr, 10);
    struct queue * queueHead = NULL;
    struct queue * queueTail = NULL;
    look(&queueHead, &queueTail, root);
    printf("\n");

    insert(&queueHead, &queueTail, &root, 11);
    insert(&queueHead, &queueTail, &root, 12);
    insert(&queueHead, &queueTail, &root, 13);

//    modify(&queueHead, &queueTail, root, 2, 88); // 2改成8
//    modify(&queueHead, &queueTail, root, 88, 2); // 2改成8
//
//    look(&queueHead, &queueTail, root);
//    printf("\n");
    // 删除insert的时候加个free即可
    deleteCreate(cnt, &queueHead, &queueTail, &root);
    deleteCreate(cnt, &queueHead, &queueTail, &root);
    deleteCreate(cnt, &queueHead, &queueTail, &root);
    deleteCreate(cnt, &queueHead, &queueTail, &root);
    deleteCreate(cnt, &queueHead, &queueTail, &root);
    look(&queueHead, &queueTail, root);
    printf("\n");

    // insert 不算进cnt里面 如果不创建 cnt就是0
    freeTree(cnt, &queueHead, &queueTail, &root);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只微

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值