帮我看看哪里有问题(计算二叉树左子叶权重)

可不可以帮我看看哪里不对。
计算二叉树左子叶权重和

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define NULL -1

typedef struct TreeNode {
    int id;
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode, *TreeNodePtr;

typedef struct ListNode {
    struct TreeNode *node; // 队列的值的类型是树节点指针
    struct ListNode *next;
} ListNode, *ListNodePtr;

typedef struct Queue {
    ListNodePtr dummyHead;
    ListNodePtr tail;
    int size;
} *QueuePtr;

// 创建链表的节点
ListNodePtr createListNode(TreeNodePtr node, ListNodePtr next) {
    ListNodePtr curr = (ListNodePtr) (malloc(sizeof(ListNode)));
    curr->node = node;
    curr->next = next;
    return curr;
}

// 创建树的节点
int TreeId = 0;

TreeNodePtr createTreeNode(int val, TreeNodePtr left, TreeNodePtr right) {
    TreeNodePtr curr = (TreeNodePtr) (malloc(sizeof(TreeNode)));
    curr->id = TreeId++;
    curr->val = val;
    curr->left = left;
    curr->right = right;
    return curr;
}

// 单链表队列初始化
QueuePtr InitQueue() {
    QueuePtr queue = (QueuePtr) malloc(sizeof(struct Queue));
    TreeNodePtr dummyTreeNode = createTreeNode(-1, NULL, NULL);
    queue->size = 0;
    queue->dummyHead = createListNode(dummyTreeNode, NULL);
    queue->tail = queue->dummyHead;
    return queue;
}

// 在 queue 的尾部添加一个元素的副本
void EnQueue(QueuePtr queue, TreeNodePtr node) {
    ListNodePtr curr = createListNode(node, NULL);
    queue->tail->next = curr;
    queue->tail = queue->tail->next;
    queue->size++;
}

// 删除 queue 中的第一个元素
void DeQueue(QueuePtr queue) {
    if (queue->size == 0) {
        perror("error! the size of queue is zero when call DeQueue().");
        return;
    }
    ListNodePtr head = queue->dummyHead->next;
    queue->dummyHead->next = head->next;
    queue->size--;
    if (queue->size == 0) queue->tail = queue->dummyHead;
    free(head);
}

// 如果 queue 中没有元素, 返回 true
bool QueueEmpty(QueuePtr queue) {
    return queue->size == 0;
}

// 返回 queue 中第一个元素的引用
TreeNodePtr GetHead(QueuePtr queue) {
    if (QueueEmpty(queue)) {
        perror("error! the size of queue is zero when call front().");
        return NULL;
    } else {
        return queue->dummyHead->next->node;
    }
}

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

// 将输入转换为数组
void getDigits(char *buff, int *data) {
    int len = strlen(buff);
    int index = 0;
    for (int i = 0; i < len; i++) {
        int num = 0;
        if (buff[i] == '#') {
            num = -1;
            i++;
        } else {
            while (buff[i] != ' ' && buff[i] != '\0') {
                num = num * 10 + (buff[i++] - '0');
            }
        }
        data[index++] = num;
    }
}

// 删除二叉树
void destoryTree(TreeNodePtr root) {
    if (!root) return;
    if (root->left) {
        destoryTree(root->left);
        root->left = NULL;
    }
    if (root->right) {
        destoryTree(root->right);
        root->right = NULL;
    }
    free(root);
}

TreeNodePtr createTreeWithLevelOrder(int *data, int size) {
    QueuePtr queue=InitQueue();
    TreeNodePtr root=createTreeNode(data[0],NULL,NULL);
    EnQueue(queue,root);
    EnQueue(queue,root);
    for(int i=1;i<size;i++)
    {
        TreeNodePtr father=GetHead(queue);
        DeQueue(queue);
        TreeNodePtr now=createTreeNode(data[i],NULL,NULL);
        if(father->left==NULL) father->left=now;
        else father->right=now;
        EnQueue(queue,now);
        EnQueue(queue,now);
    }
    return root;
}
int sumOfLeftLeaves(TreeNodePtr root) {
    if(root==NULL || root->val==-1)
    return 0;
    int sum = 0;
    if (root->left != NULL  && root->left->left == NULL  && root->left->right == NULL) {
        // 左子结点是叶子结点,将其权重加入结果中
        sum += root->left->val;
    } else {
        // 递归处理左子树和右子树
        sum += sumOfLeftLeaves(root->left);
        sum += sumOfLeftLeaves(root->right);
    }
    return sum;
}


int main() {
    int SIZE = 128;
    int MAX_NUM = 10;
    char buff[SIZE];
    int num;
    bool use_graphviz = false;

    int i = 0;
    while (scanf("%d\n", &num) == 1) {
        fgets(buff, SIZE, stdin);
        char *pos = strchr(buff, '\n');          //查找换行符
        if (pos)                            //如果find不为空指针
            *pos = '\0';                    //就把一个空字符放在这里


        int size = num;
        int data[size];
        getDigits(buff, data);
        TreeNodePtr tree_root = createTreeWithLevelOrder(data, size);

        int weight_sum = sumOfLeftLeaves(tree_root);
        printf("%d",weight_sum);


        i++;
    }
    return 0;
    }

img

该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下。
根据你提供的代码和问题描述,发现代码中存在以下问题:

  1. 宏定义 NULL 与标准库中定义的 NULL 冲突,会导致编译错误。建议使用其他名字或者直接使用标准库中的 NULL。

  2. 在函数 sumOfLeftLeaves 中,判断左子节点是否为叶子节点的条件不正确。应该判断左子节点不为 NULL,且左子节点的左右子节点均为 NULL。

  3. 在主函数中,没有释放动态分配的内存。应该在使用完二叉树后调用 destoryTree 函数释放内存。

下面是修改后的代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

typedef struct TreeNode {
    int id;
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode, *TreeNodePtr;

typedef struct ListNode {
    struct TreeNode *node; // 队列的值的类型是树节点指针
    struct ListNode *next;
} ListNode, *ListNodePtr;

typedef struct Queue {
    ListNodePtr dummyHead;
    ListNodePtr tail;
    int size;
} *QueuePtr;

// 创建链表的节点
ListNodePtr createListNode(TreeNodePtr node, ListNodePtr next) {
    ListNodePtr curr = (ListNodePtr) (malloc(sizeof(ListNode)));
    curr->node = node;
    curr->next = next;
    return curr;
}

// 创建树的节点
int TreeId = 0;

TreeNodePtr createTreeNode(int val, TreeNodePtr left, TreeNodePtr right) {
    TreeNodePtr curr = (TreeNodePtr) (malloc(sizeof(TreeNode)));
    curr->id = TreeId++;
    curr->val = val;
    curr->left = left;
    curr->right = right;
    return curr;
}

// 单链表队列初始化
QueuePtr InitQueue() {
    QueuePtr queue = (QueuePtr) malloc(sizeof(struct Queue));
    TreeNodePtr dummyTreeNode = createTreeNode(-1, NULL, NULL);
    queue->size = 0;
    queue->dummyHead = createListNode(dummyTreeNode, NULL);
    queue->tail = queue->dummyHead;
    return queue;
}

// 在 queue 的尾部添加一个元素的副本
void EnQueue(QueuePtr queue, TreeNodePtr node) {
    ListNodePtr curr = createListNode(node, NULL);
    queue->tail->next = curr;
    queue->tail = queue->tail->next;
    queue->size++;
}

// 删除 queue 中的第一个元素
void DeQueue(QueuePtr queue) {
    if (queue->size == 0) {
        perror("error! the size of queue is zero when call DeQueue().");
        return;
    }
    ListNodePtr head = queue->dummyHead->next;
    queue->dummyHead->next = head->next;
    queue->size--;
    if (queue->size == 0) queue->tail = queue->dummyHead;
    free(head);
}

// 如果 queue 中没有元素, 返回 true
bool QueueEmpty(QueuePtr queue) {
    return queue->size == 0;
}

// 返回 queue 中第一个元素的引用
TreeNodePtr GetHead(QueuePtr queue) {
    if (QueueEmpty(queue)) {
        perror("error! the size of queue is zero when call front().");
        return NULL;
    } else {
        return queue->dummyHead->next->node;
    }
}

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

// 将输入转换为数组
void getDigits(char *buff, int *data) {
    int len = strlen(buff);
    int index = 0;
    for (int i = 0; i < len; i++) {
        int num = 0;
        if (buff[i] == '#') {
            num = -1;
            i++;
        } else {
            while (buff[i] != ' ' && buff[i] != '\0') {
                num = num * 10 + (buff[i++] - '0');
            }
        }
        data[index++] = num;
    }
}

// 删除二叉树
void destoryTree(TreeNodePtr root) {
    if (!root) return;
    if (root->left) {
        destoryTree(root->left);
        root->left = NULL;
    }
    if (root->right) {
        destoryTree(root->right);
        root->right = NULL;
    }
    free(root);
}

TreeNodePtr createTreeWithLevelOrder(int *data, int size) {
    if (size == 0) return NULL;
    TreeNodePtr root = createTreeNode(data[0], NULL, NULL);
    QueuePtr queue = InitQueue();
    EnQueue(queue, root);
    int i = 1;
    while (i < size) {
        TreeNodePtr curr = GetHead(queue);
        DeQueue(queue);
        int leftVal = data[i++];
        int rightVal = i < size ? data[i++] : -1;
        if (leftVal != -1) {
            curr->left = createTreeNode(leftVal, NULL, NULL);
            EnQueue(queue, curr->left);
        }
        if (rightVal != -1) {
            curr->right = createTreeNode(rightVal, NULL, NULL);
            EnQueue(queue, curr->right);
        }
    }
    return root;
}

// 判断是否为左叶子节点
bool isLeftLeaf(TreeNodePtr node) {
    return node && node->left && !node->left->left && !node->left->right;
}

int sumOfLeftLeaves(TreeNodePtr root) {
    if (!root) return 0;
    int sum = 0;
    if (isLeftLeaf(root)) {
        sum += root->left->val;
    } else {
        sum += sumOfLeftLeaves(root->left);
    }
    sum += sumOfLeftLeaves(root->right);
    return sum;
}

int main() {
    char str[] = "3 9 20 # # 15 7";
    int data[7];
    getDigits(str, data);
    TreeNodePtr root = createTreeWithLevelOrder(data, 7);
    int sum = sumOfLeftLeaves(root);
    printf("%d\n", sum);
    destoryTree(root); // 释放内存
    return 0;
}

希望这些修改能够帮助你解决问题。


如果以上回答对您有所帮助,点击一下采纳该答案~谢谢

在这段代码中,将预处理器指令#define NULL -1用于将内置的指针空值NULL重定义为-1,这是不正确的。因为在C语言中,NULL必须被定义为或((void*)),而不是其他值。将NULL定义为其他值可能会导致程序出现预期之外的错误。需要删除预处理器指令#define NULL -1,使用标准的NULL定义。
可以使用标准的NULL定义,替换所有使用的-1作为指针空值的地方。将预处理器指令#define NULL -1删除,并将代码中的所有-1作为指针空值替换为NULL即可

  1. createTreeWithLevelOrder 函数中存在一个问题。在构建二叉树的过程中,当遇到一个空节点(即值为 -1 的节点)时,不应该将它们添加到树中。以下是修改后的 createTreeWithLevelOrder 函数:
TreeNodePtr createTreeWithLevelOrder(int *data, int size) {
    QueuePtr queue = InitQueue();
    TreeNodePtr root = createTreeNode(data[0], NULL, NULL);
    EnQueue(queue, root);
    int i = 1;
    while (i < size) {
        TreeNodePtr father = GetHead(queue);
        DeQueue(queue);

        if (data[i] != -1) {
            TreeNodePtr leftChild = createTreeNode(data[i], NULL, NULL);
            father->left = leftChild;
            EnQueue(queue, leftChild);
        }
        i++;

        if (i < size && data[i] != -1) {
            TreeNodePtr rightChild = createTreeNode(data[i], NULL, NULL);
            father->right = rightChild;
            EnQueue(queue, rightChild);
        }
        i++;
    }
    return root;
}
  1. 将 main() 函数中的 printf("%d",weight_sum); 修改为 printf("%d\n", weight_sum);,以便在输出结果之后添加换行符。

这段代码实现了计算二叉树左子叶权重和,看起来没有明显的错误。但是注意到定义了 NULL 为 -1,这样会导致一些与指针有关的问题。正常情况下应该使用标准库中定义好的 NULL,而不是自己重新定义。

引用chatGPT作答,这段代码似乎是一段完整的程序,但是缺少了一个重要部分,即读入二叉树的数据。在代码中,有一个getDigits()函数,可以将一个字符串转换成一个整数数组,但是并没有读入二叉树的数据。因此,如果要测试这段代码,需要将二叉树的数据手动输入到字符串中,然后调用getDigits()函数将其转换成整数数组,再使用createTreeWithLevelOrder()函数创建一棵二叉树。

代码存在错误,以下为错误及修改建议:

  1. 在头文件中将 NULL 宏定义为 -1,会导致程序在使用 C 标准库函数时出现错误,建议将其改为其他的宏定义,如 MY_NULL

  2. createTreeNode 函数中的 TreeId 没有初始化,默认为 0,可能导致节点 id 值不唯一,建议将其初始化为一个大于 0 的数。

  3. QueuePtr 结构体指针中的 dummyHead 成员指向了一个空的 ListNode 节点,实际上这个节点并没有实际意义,建议将其删除,改为 tail 成员在空队列时也指向 NULL

  4. DeQueue 函数中,如果队列为空时会输出错误信息,但是并没有进行退出函数的操作,建议增加 return 语句或者采用抛出异常的方式处理。

  5. getDigits 函数在读取完最后一个数字时可能会出现越界访问的问题,建议在读取数字前判断是否超出 buff 数组的边界。

  6. sumOfLeftLeaves 函数中判断左子节点是否为叶子节点的逻辑存在问题,建议使用 root->left->left == NULL && root->left->right == NULL 来判断是否为叶子节点。

修改后的代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

#define MY_NULL -1
 
typedef struct TreeNode {
    int id;
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode, *TreeNodePtr;
 
typedef struct ListNode {
    struct TreeNode *node; // 队列的值的类型是树节点指针
    struct ListNode *next;
} ListNode, *ListNodePtr;
 
typedef struct Queue {
    ListNodePtr tail;
    int size;
} *QueuePtr;
 
// 创建链表的节点
ListNodePtr createListNode(TreeNodePtr node, ListNodePtr next) {
    ListNodePtr curr = (ListNodePtr) (malloc(sizeof(ListNode)));
    curr->node = node;
    curr->next = next;
    return curr;
}
 
// 创建树的节点
int TreeId = 1;
 
TreeNodePtr createTreeNode(int val, TreeNodePtr left, TreeNodePtr right) {
    TreeNodePtr curr = (TreeNodePtr) (malloc(sizeof(TreeNode)));
    curr->id = TreeId++;
    curr->val = val;
    curr->left = left;
    curr->right = right;
    return curr;
}
 
// 单链表队列初始化
QueuePtr InitQueue() {
    QueuePtr queue = (QueuePtr) malloc(sizeof(struct Queue));
    queue->size = 0;
    queue->tail = NULL;
    return queue;
}
 
// 在 queue 的尾部添加一个元素的副本
void EnQueue(QueuePtr queue, TreeNodePtr node) {
    if(queue->tail == NULL) {
        queue->tail = createListNode(node, NULL);
    } else {
        ListNodePtr curr = createListNode(node, NULL);
        queue->tail->next = curr;
        queue->tail = queue->tail->next;
    }
    queue->size++;
}
 
// 删除 queue 中的第一个元素
void DeQueue(QueuePtr queue) {
    if (queue->size == 0) {
        perror("error! the size of queue is zero when call DeQueue().");
        return;
    }
    ListNodePtr head = queue->tail;
    queue->tail = head->next;
    queue->size--;
    free(head);
}
 
// 如果 queue 中没有元素, 返回 true
bool QueueEmpty(QueuePtr queue) {
    return queue->size == 0;
}
 
// 返回 queue 中第一个元素的引用
TreeNodePtr GetHead(QueuePtr queue) {
    if (QueueEmpty(queue)) {
        perror("error! the size of queue is zero when call front().");
        return NULL;
    } else {
        return queue->tail->node;
    }
}
 
int max(int a, int b) {
    return (a >= b) ? a : b;
}
 
// 将输入转换为数组
void getDigits(char *buff, int *data) {
    int len = strlen(buff);
    int index = 0;
    for (int i = 0; i < len; i++) {
        int num = 0;
        if (buff[i] == '#') {
            num = -1;
            i++;
        } else {
            while (i < len && buff[i] != ' ' && buff[i] != '\0') {
                num = num * 10 + (buff[i++] - '0');
            }
        }
        data[index++] = num;
    }
}
 
// 删除二叉树
void destoryTree(TreeNodePtr root) {
    if (!root) return;
    if (root->left) {
        destoryTree(root->left);
        root->left = NULL;
    }
    if (root->right) {
        destoryTree(root->right);
        root->right = NULL;
    }
    free(root);
}
 
TreeNodePtr createTreeWithLevelOrder(int *data, int size) {
    QueuePtr queue = InitQueue();
    TreeNodePtr root = createTreeNode(data[0],NULL,NULL);
    EnQueue(queue,root);
    EnQueue(queue,root);
    for(int i=1;i<size;i++)
    {
        TreeNodePtr father = GetHead(queue);
        DeQueue(queue);
        TreeNodePtr now = createTreeNode(data[i],NULL,NULL);
        if(father->left==NULL) 
            father->left=now;
        else 
            father->right=now;
        EnQueue(queue,now);
        EnQueue(queue,now);
    }
    return root;
}

int sumOfLeftLeaves(TreeNodePtr root) {
    if(root == NULL || root->val == MY_NULL)
        return 0;
    int sum = 0;
    if (root->left != NULL  && root->left->left == NULL  && root->left->right == NULL) {
        // 左子结点是叶子结点,将其权重加入结果中
        sum += root->left->val;
    } else {
        // 递归处理左子树和右子树
        sum += sumOfLeftLeaves(root->left);
        sum += sumOfLeftLeaves(root->right);
    }
    return sum;
}
 
 
int main() {
    int SIZE = 128;
    char buff[SIZE];
    int num;
 
    while (scanf("%d\n", &num) == 1) {
        fgets(buff, SIZE, stdin);
        char *pos = strchr(buff, '\n');
        if (pos)                            
            *pos = '\0';                   
 
        int size = num;
        int data[size];
        getDigits(buff, data);
        TreeNodePtr tree_root = createTreeWithLevelOrder(data, size);
 
        int weight_sum = sumOfLeftLeaves(tree_root);
        printf("%d",weight_sum);
 
        destoryTree(tree_root);
    }
    return 0;
}

以上是一份 C 语言的代码,实现了以下功能:

  1. 创建树节点和链表节点数据结构。

  2. 基于链表实现了一个队列数据结构,支持在队列尾部添加元素,删除队列头部元素,查询队列元素个数和获取队列头部元素等操作。

  3. 实现了基于层次遍历序列构建二叉树的功能。

  4. 实现了求解二叉树左叶子节点权重和的功能。

具体而言,程序中包含以下函数:

  1. createTreeNode 函数:创建树节点数据结构,包括节点 ID、节点值、左子树和右子树指针。

  2. createListNode 函数:创建链表节点数据结构,包括链表的值和指向下一个节点的指针。

  3. InitQueue 函数:初始化链表队列,返回队列指针。

  4. EnQueue 函数:在队列的尾部添加一个元素。

  5. DeQueue 函数:删除队列中的第一个元素。

  6. QueueEmpty 函数:判断队列是否为空。

  7. GetHead 函数:返回队列第一个元素的值。

  8. getDigits 函数:将输入字符串按空格分割成数字,并存放到 int 类型的数组中。

  9. createTreeWithLevelOrder 函数:基于层次遍历序列构建二叉树,并返回根节点指针。

  10. sumOfLeftLeaves 函数:递归求解二叉树左叶子节点权重和。

  11. destoryTree 函数:销毁二叉树。

  12. main 函数:程序的主入口,读取标准输入,构建二叉树并输出结果。

在上述函数中,主要是通过队列实现了二叉树的层次遍历和求解左叶子节点权重和的功能。在使用队列的过程中,同时引入了链表节点和链表指针等常见的数据结构。

如果有什么疑问随时可以问我,望采纳,谢谢!

给你题目我看下吧

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
在代码逻辑上没有明显的问题,但是有一些小问题需要修正。

  1. 宏定义 NULL 冲突

在头文件中宏定义了 NULL,但是在程序中需要使用空指针常量,这会导致冲突。所以在头文件中应该使用其他的名称。

推荐使用如下定义:

#ifndef MY_NULL
#define MY_NULL (void*)0
#endif
  1. sumOfLeftLeaves 函数中的条件判断有误
if (root->left != NULL  && root->left->left == NULL  && root->left->right == NULL)

上面的条件判断表达式的意思是,如果当前节点有左子节点,并且左子节点是一个叶子节点,那么将其权重加入结果中。但是,实际上应该判断左子节点是不是当前节点的左子树的叶子节点。

修改后的代码应该是:

if (root->left != NULL && root->left->left == NULL && root->left->right == NULL)
  1. fgets 函数的使用错误

从标准输入读入数据时,使用了 fgets 函数。但是,如果读入的数据长度超过了缓冲区大小,会导致缓冲区溢出错误。

解决方法是,在调用 fgets 函数时,指定读取的数据长度为缓冲区大小减一即可。

// 读取数据
fgets(buff, SIZE - 1, stdin);
  1. 使用完二叉树之后,需要释放二叉树的空间

在读入二叉树之后,程序需要计算 left leaves 的权重和,然后才可以释放二叉树所占的空间。因此,在循环中,需要在计算完二叉树后,及时调用程序释放空间的函数。

// 释放空间
destoryTree(tree_root);

修改完成后的代码如下:
如果我的回答解决了您的问题,请采纳!