102二叉树的层次遍历、107.二叉树的层次遍历II、199.二叉树的右视图、637.二叉树的层平均值、429.N叉树的层序遍历、515.在每个树行中找最大值、116.填充每个节点的下一个右侧节点指针

题目链接/文章讲解/视频讲解: 代码随想录

1.102二叉树的层次遍历

不了解队列的,可以看一看这个队的实现及思路-CSDN博客

1.1分析及思路

用队列实现,怎么一层一层的遍历那,就是先把一层的结点放入队列中,然后出队时,在队列尾部传入其左右孩子即可。当一层遍历完毕之后剩下的就是它的下一层。在出队时,用一个数值存储一层的数目,这样方便知道该层遍历完毕。这样输出几个之后剩下的就是下一层的元素,我们此时读取队列中的元素个数,就能获得下一层的元素个数。

1.2代码及注释

// 定义树节点结构体
typedef struct TreeNode ElemType;
// 定义队列最大容量,题目中结点数为0-2000最大为2001个
#define MaxSize 2001

// 定义顺序队列结构体
typedef struct {
    ElemType* data[MaxSize]; // 数据数组
    int size; // 队列当前元素个数
    int front, rear; // 队列头指针和尾指针
} SqQueue;

// 初始化队列
void InitQueue(SqQueue* Queue) {
    Queue->rear = Queue->front = 0; // 队列头尾指针初始位置为0
    Queue->size = 0; // 队列初始元素个数为0
}

// 判断队列是否为空
bool isEmpty(SqQueue Queue) {
    if (Queue.rear == Queue.front) // 头尾指针相等表示队列为空
        return true;
    return false;
}

// 入队操作
bool EnQueue(SqQueue* Queue, ElemType* x) {
    if ((Queue->rear + 1) % MaxSize == Queue->front) // 判断队列是否已满
        return false;
    
    Queue->data[Queue->rear] = x; // 将新节点加入队列
    Queue->rear = (Queue->rear + 1) % MaxSize; // 更新尾指针
    Queue->size++; // 队列元素个数加1
    return true;
}

// 出队操作
bool DeQueue(SqQueue* Queue, ElemType* data) {
    if (Queue->rear == Queue->front) // 队列为空
        return false;
    
    *data = *(Queue->data[Queue->front]); // 获取队头元素
    Queue->front = (Queue->front + 1) % MaxSize; // 更新头指针
    Queue->size--; // 队列元素个数减1
    return true;
}

// 层序遍历函数,返回二维数组
int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes) {
    *returnSize = 0; // 初始化返回的二维数组行数为0
    if (root == NULL) 
        return NULL; // 根节点为空则返回空
    
    int** result = (int**)malloc(sizeof(int*) * MaxSize); // 分配二维数组空间
    *returnColumnSizes = (int*)malloc(sizeof(int) * MaxSize); // 分配列大小数组空间

    SqQueue queue;
    InitQueue(&queue); // 初始化队列
    EnQueue(&queue, root); // 根节点入队

    while (!isEmpty(queue)) { // 遍历队列
        int levelSize = queue.size; // 当前层的节点个数
        result[*returnSize] = (int*)malloc(sizeof(int) * levelSize); // 分配当前行的空间
        (*returnColumnSizes)[*returnSize] = levelSize; // 记录当前行的节点个数

        for (int i = 0; i < levelSize; i++) {
            struct TreeNode node;
            DeQueue(&queue, &node); // 出队节点
            result[*returnSize][i] = node.val; // 记录节点值
            if (node.left)
                EnQueue(&queue, node.left); // 左子节点入队
            if (node.right)
                EnQueue(&queue, node.right); // 右子节点入队
        }
        (*returnSize)++; // 行数加1,一层遍历结束,开启下一层的遍历
    }
    return result; // 返回二维数组
}

1.3重点语句讲解

 int** result = (int**)malloc(sizeof(int*) * MaxSize); // 分配二维数组空间

定义一个二维数组,用来存储返回的结点值。因为result是int**类型,所以返回值也为int**。

(sizeof(int*) * MaxSize),二维数组中存储的一维数组,一维数组存储int类型元素。所以是sizeof(int*)。MaxSize因为结点最大为2001,所以要设置为最大值。最多有2001行。

*returnColumnSizes = (int*)malloc(sizeof(int) * MaxSize); // 分配列大小数组空间

  returnColumnSizes是一个int**类型,所以*returnColumnSizes是一个int*类型它指向int*,用于存储一个数组。MaxSize是2001,最大数量为2001,所以要设计为2001。

        result[*returnSize] = (int*)malloc(sizeof(int) * levelSize); // 分配当前行的空间
        (*returnColumnSizes)[*returnSize] = levelSize; // 记录当前行的节点个数

result[*returnSize]是int*类型,要用来存储int型元素。所以是sizeof(int),leveSize代表每一层的结点个数,所以sizeof(int) * levelSize就是所需空间。

  (*returnColumnSizes)[*returnSize]就是一个一维数组,用来存储每一层的元素个数。

2.107.二叉树的层次遍历II

2.1分析及思路

反转思路请看:代码随想录算法训练营第八天| 344.反转字符串 、 541. 反转字符串II、 卡码网:54.替换数字 、 151.翻转字符串里的单词 、卡码网:55.右旋转字符串-CSDN博客

和上一题类似只是进行了一个反转。

我们只需把二维数组看成一维数组进行反转即可。

2.2代码及注释

// 定义树节点结构体
typedef struct TreeNode ElemType;
// 定义队列最大容量,题目中结点数为0-2000最大为2001个
#define MaxSize 2001

// 定义顺序队列结构体
typedef struct {
    ElemType* data[MaxSize]; // 数据数组
    int size; // 队列当前元素个数
    int front, rear; // 队列头指针和尾指针
} SqQueue;

// 初始化队列
void InitQueue(SqQueue* Queue) {
    Queue->rear = Queue->front = 0; // 队列头尾指针初始位置为0
    Queue->size = 0; // 队列初始元素个数为0
}

// 判断队列是否为空
bool isEmpty(SqQueue Queue) {
    if (Queue.rear == Queue.front) // 头尾指针相等表示队列为空
        return true;
    return false;
}

// 入队操作
bool EnQueue(SqQueue* Queue, ElemType* x) {
    if ((Queue->rear + 1) % MaxSize == Queue->front) // 判断队列是否已满
        return false;
    
    Queue->data[Queue->rear] = x; // 将新节点加入队列
    Queue->rear = (Queue->rear + 1) % MaxSize; // 更新尾指针
    Queue->size++; // 队列元素个数加1
    return true;
}

// 出队操作
bool DeQueue(SqQueue* Queue, ElemType* data) {
    if (Queue->rear == Queue->front) // 队列为空
        return false;
    
    *data = *(Queue->data[Queue->front]); // 获取队头元素
    Queue->front = (Queue->front + 1) % MaxSize; // 更新头指针
    Queue->size--; // 队列元素个数减1
    return true;
}
// 定义一个函数用于翻转数组
void reverse(int** result, int left, int right, int** returnColumnSizes){
    // 当左指针小于右指针时进行循环
    while(left < right){
        // 交换左右指针对应的数组元素指针和列大小
        int* TempPointer = result[left];
        int Temp = (*returnColumnSizes)[left];
        result[left] = result[right];
        result[right] = TempPointer;
        (*returnColumnSizes)[left] = (*returnColumnSizes)[right];
        (*returnColumnSizes)[right] = Temp;
        // 移动左指针和右指针
        left++;
        right--;
    }
}

// 定义一个函数用于层序遍历二叉树并返回倒序结果
int** levelOrderBottom(struct TreeNode* root, int* returnSize, int** returnColumnSizes) {
    // 初始化返回大小为0
    *returnSize = 0;
    // 如果根节点为空,则返回空指针
    if(root == NULL)
        return NULL;
    
    // 分配存储结果和列大小的内存空间
    int** result = (int**)malloc(sizeof(int*) * MaxSize);
    *returnColumnSizes = (int*)malloc(sizeof(int) * MaxSize);
    int QueueLen = 0;

    // 初始化队列
    SqQueue Queue;
    InitQueue(&Queue);
    EnQueue(&Queue, root);

    // 循环进行层序遍历
    while(!isEmpty(Queue)){
        QueueLen = Queue.size;
        // 分配每一层的数组空间
        result[*returnSize] = (int*)malloc(sizeof(int) * QueueLen);
        (*returnColumnSizes)[*returnSize] = QueueLen;

        // 遍历当前层的节点并存储值,将下一层节点入队
        for(int i = 0; i < QueueLen; i++){
            struct TreeNode TempNode;
            DeQueue(&Queue, &TempNode);
            result[*returnSize][i] = TempNode.val;
            if(TempNode.left)
                EnQueue(&Queue, TempNode.left);
            if(TempNode.right)
                EnQueue(&Queue, TempNode.right);
        }
        (*returnSize)++;
    }
    // 调用翻转函数将结果数组逆序
    reverse(result, 0, (*returnSize) - 1, returnColumnSizes);
    // 返回倒序结果数组
    return result;
}

2.3重点语句讲解

// 定义一个函数用于翻转数组
void reverse(int** result, int left, int right, int** returnColumnSizes){
    // 当左指针小于右指针时进行循环
    while(left < right){
        // 交换左右指针对应的数组元素指针和列大小
        int* TempPointer = result[left];
        int Temp = (*returnColumnSizes)[left];
        result[left] = result[right];
        result[right] = TempPointer;
        (*returnColumnSizes)[left] = (*returnColumnSizes)[right];
        (*returnColumnSizes)[right] = Temp;
        // 移动左指针和右指针
        left++;
        right--;
    }
}

result[left]和result[right]中存储的是一个地址,是一个指向一维数组的地址。交换它们两个的地址就实现了反转。

3.199.二叉树的右视图

3.1分析及思路

思路很简单,每一层的最后一个元素,记入结果数组即可。

3.2代码及注释

// 定义树节点结构体
typedef struct TreeNode ElemType;
// 定义队列最大容量返回[0,100],最大数量为101
#define MaxSize 101

// 定义顺序队列结构体
typedef struct {
    ElemType* data[MaxSize]; // 数据数组
    int size; // 队列当前元素个数
    int front, rear; // 队列头指针和尾指针
} SqQueue;

// 初始化队列
void InitQueue(SqQueue* Queue) {
    Queue->rear = Queue->front = 0; // 队列头尾指针初始位置为0
    Queue->size = 0; // 队列初始元素个数为0
}

// 判断队列是否为空
bool isEmpty(SqQueue Queue) {
    if (Queue.rear == Queue.front) // 头尾指针相等表示队列为空
        return true;
    return false;
}

// 入队操作
bool EnQueue(SqQueue* Queue, ElemType* x) {
    if ((Queue->rear + 1) % MaxSize == Queue->front) // 判断队列是否已满
        return false;
    
    Queue->data[Queue->rear] = x; // 将新节点加入队列
    Queue->rear = (Queue->rear + 1) % MaxSize; // 更新尾指针
    Queue->size++; // 队列元素个数加1
    return true;
}

// 出队操作
bool DeQueue(SqQueue* Queue, ElemType* data) {
    if (Queue->rear == Queue->front) // 队列为空
        return false;
    
    *data = *(Queue->data[Queue->front]); // 获取队头元素
    Queue->front = (Queue->front + 1) % MaxSize; // 更新头指针
    Queue->size--; // 队列元素个数减1
    return true;
}


int* rightSideView(struct TreeNode* root, int* returnSize) {
    // 初始化返回大小为0
    *returnSize = 0;
    // 如果根节点为空,返回NULL
    if(root == NULL)
        return NULL;
    // 分配结果数组的内存空间
    int* result = (int*)malloc(sizeof(int)*MaxSize);
    // 初始化队列长度为0
    int QueueLen = 0;
    // 初始化一个队列
    SqQueue Queue;
    InitQueue(&Queue);
    // 将根节点入队
    EnQueue(&Queue,root);

    // 当队列不为空时
    while(!isEmpty(Queue)){
        // 获取当前队列长度
        QueueLen = Queue.size;
        // 遍历当前层的节点
        for(int i=0;i<QueueLen;i++){
            struct TreeNode Node;
            // 出队一个节点
            DeQueue(&Queue,&Node);
            // 如果是当前层的最后一个节点,将其值添加到结果数组中
            if(i == QueueLen - 1)
                result[(*returnSize)++] = Node.val;
            // 如果左子节点存在,入队
            if(Node.left != NULL)
                EnQueue(&Queue,Node.left);
            // 如果右子节点存在,入队
            if(Node.right != NULL)
                EnQueue(&Queue,Node.right);
        }
    }
    // 返回结果数组
    return result;
}

4.637.二叉树的层平均值

4.1分析及思路

把层序遍历的结点加一起,进行每一层求平均值。较为简单

4.2代码及注释

// 定义树节点结构体
typedef struct TreeNode ElemType;
// 定义队列最大容量,题目中结点数为0-10000最大为10001个
#define MaxSize 10001

// 定义顺序队列结构体
typedef struct {
    ElemType* data[MaxSize]; // 数据数组
    int size; // 队列当前元素个数
    int front, rear; // 队列头指针和尾指针
} SqQueue;

// 初始化队列
void InitQueue(SqQueue* Queue) {
    Queue->rear = Queue->front = 0; // 队列头尾指针初始位置为0
    Queue->size = 0; // 队列初始元素个数为0
}

// 判断队列是否为空
bool isEmpty(SqQueue Queue) {
    if (Queue.rear == Queue.front) // 头尾指针相等表示队列为空
        return true;
    return false;
}

// 入队操作
bool EnQueue(SqQueue* Queue, ElemType* x) {
    if ((Queue->rear + 1) % MaxSize == Queue->front) // 判断队列是否已满
        return false;
    
    Queue->data[Queue->rear] = x; // 将新节点加入队列
    Queue->rear = (Queue->rear + 1) % MaxSize; // 更新尾指针
    Queue->size++; // 队列元素个数加1
    return true;
}

// 出队操作
bool DeQueue(SqQueue* Queue, ElemType* data) {
    if (Queue->rear == Queue->front) // 队列为空
        return false;
    
    *data = *(Queue->data[Queue->front]); // 获取队头元素
    Queue->front = (Queue->front + 1) % MaxSize; // 更新头指针
    Queue->size--; // 队列元素个数减1
    return true;
}

double* averageOfLevels(struct TreeNode* root, int* returnSize) {
    *returnSize = 0; // 初始化返回数组的大小为0
    if(root == NULL)
        return NULL; // 如果根节点为空,直接返回空指针
    
    double* result = (double*)malloc(sizeof(double)*MaxSize); // 分配存放结果的数组空间
    int QueueLen = 0; // 初始化队列长度为0
    SqQueue Queue; // 定义一个顺序队列
    struct TreeNode Node; // 定义一个树节点
    InitQueue(&Queue); // 初始化队列
    EnQueue(&Queue,root); // 将根节点入队

    while(!isEmpty(Queue)){ // 当队列不为空时循环
        QueueLen = Queue.size; // 获取当前队列长度
        double averageTemp = 0; // 初始化当前层的平均值为0
        for(int i=0;i<QueueLen;i++){ // 遍历当前层的所有节点
            DeQueue(&Queue,&Node); // 出队一个节点
            averageTemp = averageTemp + Node.val; // 累加当前层节点的值
            if(Node.left != NULL)
                EnQueue(&Queue,Node.left); // 如果左子节点不为空,入队
            if(Node.right != NULL)
                EnQueue(&Queue,Node.right); // 如果右子节点不为空,入队
        }
        result[(*returnSize)++] = averageTemp / QueueLen; // 计算当前层的平均值并存入结果数组
    }
    return result; // 返回结果数组
}

5.429.N叉树的层序遍历

5.1分析及思路

思路与二叉树的层次遍历类似,无非就是多加了几个孩子结点。

5.2代码及注释

// 定义树节点结构体
typedef struct Node ElemType;
// 定义队列最大容量,题目中结点数为0-10000最大为10001个
#define MaxSize 10001

// 定义顺序队列结构体
typedef struct {
    ElemType data[MaxSize]; // 数据数组
    int size; // 队列当前元素个数
    int front, rear; // 队列头指针和尾指针
} SqQueue;

// 初始化队列
void InitQueue(SqQueue* Queue) {
    Queue->rear = Queue->front = 0; // 队列头尾指针初始位置为0
    Queue->size = 0; // 队列初始元素个数为0
}

// 判断队列是否为空
bool isEmpty(SqQueue Queue) {
    if (Queue.rear == Queue.front) // 头尾指针相等表示队列为空
        return true;
    return false;
}

// 入队操作
bool EnQueue(SqQueue* Queue, ElemType x) {
    if ((Queue->rear + 1) % MaxSize == Queue->front) // 判断队列是否已满
        return false;
    
    Queue->data[Queue->rear] = x; // 将新节点加入队列
    Queue->rear = (Queue->rear + 1) % MaxSize; // 更新尾指针
    Queue->size++; // 队列元素个数加1
    return true;
}

// 出队操作
bool DeQueue(SqQueue* Queue, ElemType* data) {
    if ((Queue->size == 0) || (Queue->rear == Queue->front)) // 队列为空
        return false;
    
    *data = (*Queue).data[Queue->front]; // 获取队头元素
    Queue->front = (Queue->front + 1) % MaxSize; // 更新头指针
    Queue->size--; // 队列元素个数减1
    return true;
}

// 定义一个函数,返回一个二维数组,表示树的层序遍历结果
int** levelOrder(struct Node* root, int* returnSize, int** returnColumnSizes) {
    *returnSize = 0; // 初始化返回结果的大小为0
    if(root == NULL){ // 如果根节点为空,直接返回空值
        *returnColumnSizes = NULL;
        return NULL;
    }
    
    int** result = (int**)malloc(sizeof(int*)*MaxSize); // 分配存储结果的二维数组空间
    *returnColumnSizes = (int*)malloc(sizeof(int)*MaxSize); // 分配存储每层节点数量的数组空间
    SqQueue Queue; // 定义一个队列用于层序遍历
    int QueueLen = 0; // 用于记录当前层的节点数量
    InitQueue(&Queue); // 初始化队列
    EnQueue(&Queue,*root); // 将根节点入队

    while(!isEmpty(Queue)){ // 当队列不为空时循环
       QueueLen = Queue.size; // 记录当前层的节点数量
       result[*returnSize] = (int*)malloc(sizeof(int)*QueueLen); // 为当前层分配存储空间
       (*returnColumnSizes)[*returnSize] = QueueLen; // 记录当前层的节点数量
       for(int i=0;i<QueueLen;i++){ // 遍历当前层的节点
           struct Node Node;
           DeQueue(&Queue,&Node); // 出队一个节点
           result[*returnSize][i] = Node.val; // 将节点值存入结果数组
           for(int j=0;j<Node.numChildren;j++){ // 遍历当前节点的子节点
               EnQueue(&Queue,*(Node.children[j])); // 将子节点入队
           }
       }
       (*returnSize)++; // 更新返回结果的大小
    }
    return result; // 返回层序遍历结果
}

5.3重点语句及遇到的问题

    *returnSize = 0; // 初始化返回结果的大小为0
    if(root == NULL){ // 如果根节点为空,直接返回空值
        *returnColumnSizes = NULL;
        return NULL;
    }

 一开始没添加*returnColumnSizes = NULL;出现了一下错误

=================================================================
==22==ERROR: AddressSanitizer: attempting double-free on 0x62e00000c400 in thread T0:
    #0 0x7f284e21c537 in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:127
    #2 0x7f284d84cd8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)
    #3 0x7f284d84ce3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f)
0x62e00000c400 is located 0 bytes inside of 40004-byte region [0x62e00000c400,0x62e000016044)
freed by thread T0 here:
    #0 0x7f284e21c537 in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:127
    #2 0x7f284d84cd8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)
previously allocated by thread T0 here:
    #0 0x7f284e21c887 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
    #3 0x7f284d84cd8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)
SUMMARY: AddressSanitizer: double-free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:127 in __interceptor_free
==22==ABORTING

大致意思就是,企图两次释放同一空间,单独运行的时候不报错,但是提交就报错。猜测应该是,同时进行测试时,释放原来的局部静态变量,因为*returnColumnSizes没有赋初始值,所以随机释放到了该空间。如有错误还请留言。

总结,对每一个传入的参数,都要进行赋值。

 struct Node {
      int val;
      int numChildren;
      struct Node** children;
 };           
for(int j=0;j<Node.numChildren;j++){
               EnQueue(&Queue,*(Node.children[j]));
           }

存储了孩子的个数,依次传入即可。Node是一个struct Node类型,Node.children是struct Node**类型,Node.children[j]是struct Node*类型,对它进行地址取值,就是struct Node型。

6.515.在每个树行中找最大值

6.1分析及思路

层序遍历加比较值即可。

6.2代码及注释

// 定义树节点结构体
typedef struct TreeNode ElemType;
// 定义队列最大容量,题目中结点数为0-10000最大为10001个
#define MaxSize 10001

// 定义顺序队列结构体
typedef struct {
    ElemType data[MaxSize]; // 数据数组
    int size; // 队列当前元素个数
    int front, rear; // 队列头指针和尾指针
} SqQueue;

// 初始化队列
void InitQueue(SqQueue* Queue) {
    Queue->rear = Queue->front = 0; // 队列头尾指针初始位置为0
    Queue->size = 0; // 队列初始元素个数为0
}

// 判断队列是否为空
bool isEmpty(SqQueue Queue) {
    if (Queue.rear == Queue.front) // 头尾指针相等表示队列为空
        return true;
    return false;
}
//获取队头元素
bool GetTopQueue(SqQueue Queue, int* x) {
    if ((Queue.size == 0) || (Queue.rear == Queue.front)) // 队列为空
    return false;
    //Queue.data[Queue.front]是队头元素,是一个struct TreeNode型
    *x = Queue.data[Queue.front].val;
    return true;
}

// 入队操作
bool EnQueue(SqQueue* Queue, ElemType x) {
    if ((Queue->rear + 1) % MaxSize == Queue->front) // 判断队列是否已满
        return false;
    
    Queue->data[Queue->rear] = x; // 将新节点加入队列
    Queue->rear = (Queue->rear + 1) % MaxSize; // 更新尾指针
    Queue->size++; // 队列元素个数加1
    return true;
}

// 出队操作
bool DeQueue(SqQueue* Queue, ElemType* data) {
    if ((Queue->size == 0) || (Queue->rear == Queue->front)) // 队列为空
        return false;
    
    *data = (*Queue).data[Queue->front]; // 获取队头元素
    Queue->front = (Queue->front + 1) % MaxSize; // 更新头指针
    Queue->size--; // 队列元素个数减1
    return true;
}

// 定义一个指向整型数组的指针,用于存储每层最大值
int* largestValues(struct TreeNode* root, int* returnSize) {
    *returnSize = 0;
    if(root == NULL)
        return NULL;
    
    // 分配存储最大值的数组空间
    int* result = (int*)malloc(sizeof(int)*MaxSize);
    //定义一个队列
    SqQueue Queue;
    //保存队列长度
    int QueueLen;
    //临时保存结点
    struct TreeNode Node;
    //用来保存每一层的最大值
    int Max;
    InitQueue(&Queue);
    EnQueue(&Queue,*root);

    // 遍历二叉树层次,找到每层最大值并存储在result数组中
    while(!isEmpty(Queue)){
        //获取该层的元素个数
        QueueLen = Queue.size;
        //初始化每一层的Max,设为每一层的第一个元素的值
        GetTopQueue(Queue,&Max);
        for(int i=0;i<QueueLen;i++){
            //出队列
            DeQueue(&Queue,&Node);
            //若该结点元素值大于Max,则Max更新
            if(Max < Node.val)
                Max = Node.val;
            if(Node.left != NULL)//若左孩子不为空,则传入左孩子
                EnQueue(&Queue,*(Node.left));
            if(Node.right != NULL)//若右节点不为空,则传入右孩子
                EnQueue(&Queue,*(Node.right));
        }
        //存储每一层的最大值
        result[(*returnSize)++] = Max;
    }

    return result;
}

7.116.填充每个节点的下一个右侧节点指针

7.1分析及思路

用层序遍历,对每层进行next的指向。即每一层的前n-1个分别指向其对应的后一个。每一层的最后一个指向NULL。

7.2代码及注释

typedef struct Node ElemType;  // 定义结构体 Node 为 ElemType
#define MaxSize 4096// 定义队列的最大容量为 4096
 
typedef struct {
    ElemType* data[MaxSize];  // 存储元素的数组
    int size;  // 队列当前元素个数
    int front, rear;  // 队列头尾指针
} SqQueue;

void InitQueue(SqQueue* Queue) {
    Queue->rear = Queue->front = 0;  // 初始化队列头尾指针
    Queue->size = 0;  // 初始化队列元素个数为 0
}
 
bool isEmpty(SqQueue Queue) {
    if (Queue.rear == Queue.front)  // 判断队列是否为空
        return true;
    return false;
}
 
bool GetTopQueue(SqQueue Queue, ElemType** x) {
    if ((Queue.size == 0) || (Queue.rear == Queue.front))  // 判断队列是否为空或已满
    return false;
    
    *x = Queue.data[Queue.front];  // 获取队首元素
    return true;
}
 
bool EnQueue(SqQueue* Queue, ElemType* x) {
    if ((Queue->rear + 1) % MaxSize == Queue->front)  // 判断队列是否已满
        return false;
    
    Queue->data[Queue->rear] = x;  // 入队
    Queue->rear = (Queue->rear + 1) % MaxSize;  // 更新 rear 指针
    Queue->size++;  // 更新队列元素个数
    return true;
}
 
bool DeQueue(SqQueue* Queue, ElemType** data) {
    if ((Queue->size == 0) || (Queue->rear == Queue->front))  // 判断队列是否为空
        return false;
    
    *data = (*Queue).data[Queue->front];  // 出队
    Queue->front = (Queue->front + 1) % MaxSize;  // 更新 front 指针
    Queue->size--;  // 更新队列元素个数
    return true;
}
 
struct Node* connect(struct Node* root) {
    if(root == NULL)  // 判断根节点是否为空
        return NULL;
    
    SqQueue Queue;  // 定义队列
    InitQueue(&Queue);  // 初始化队列
    EnQueue(&Queue,root);  // 根节点入队
 
    while(!isEmpty(Queue)){  // 遍历队列中的节点
        int QueueLen = Queue.size;  // 获取当前队列长度
        struct Node* Node = NULL;  // 定义节点指针
        for(int i=0;i<QueueLen;i++){  // 遍历当前队列中的节点
            DeQueue(&Queue,&Node);  // 出队一个节点
            if (i < QueueLen - 1)  // 如果不是最后一个节点
                Node->next = Queue.data[Queue.front];  // 直接连接下一个节点
            if(Node->left != NULL)  // 如果左子节点不为空
                EnQueue(&Queue,Node->left);  // 左子节点入队
            if(Node->right != NULL)  // 如果右子节点不为空
                EnQueue(&Queue,Node->right);  // 右子节点入队
        }
    }
    return root;  // 返回根节点
}

如有错误还请指正。若有不明白的也可以评论。

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值