尝试建立一个树

58 阅读3分钟

root = (TreeNode*)malloc(sizeof(TreeNode)); 这句话的意思是:malloc分配一个内存空间,malloc返回的是void*,无类型指针,返回值是分配的这块空间的地址。

用(TreeNode*)强制类型转换成树节点型指针,赋值给root。因为void*不能直接赋值给别的类型的指针,所以要通过强制类型转换。root就是一个指向树节点的指针,现在他的值变成了申请这块空间的地址了。

最终建树成功的代码:

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

typedef struct TreeNode{
    int val;
    struct TreeNode* left;
    struct TreeNode* right;
} TreeNode;

void preorder (struct TreeNode* root, int* returnSize, int* ans){
    if (root == NULL)
    return;

    ans[*returnSize] = root->val;
    printf("%d\n", ans[*returnSize]);
    (*returnSize) ++;
    if (root->left != NULL)
    {
        preorder(root->left, returnSize, ans);
    }
    if (root->right != NULL)
    {
        preorder(root->right, returnSize, ans);
    }
}

int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    int* ans = (int*)malloc(sizeof(int) * 100);
    *returnSize = 0;
    preorder (root, returnSize, ans);
    return ans;
}

void TreeNodeCreate(TreeNode** pointer, int* size)
{
    *pointer = (TreeNode*)malloc(sizeof(TreeNode));
    *size ++;
    (*pointer)->left = NULL;
    (*pointer)->right = NULL;
}

int main()  
{
    int size = 0;
    TreeNode* root;
    TreeNode* newnode;
    TreeNode* lastnode;

    TreeNodeCreate(&root, &size);
    root->val = 1;

    TreeNodeCreate(&newnode, &size);
    root->right = newnode;
    newnode->val = 2;
    lastnode = newnode;

    TreeNodeCreate(&newnode, &size);
    lastnode->left = newnode;
    newnode->val = 3;

    int* returnSize = (int*)malloc(sizeof(int));
    int* ans;
    ans = preorderTraversal(root, returnSize);

    return 0;
}

bug:

“Segmentation fault”(段错误),是程序运行时常见的严重错误 “Segmentation” 源于计算机内存管理中的 “内存段(Segment)” 概念。当程序试图访问不被允许的内存段(例如未分配的内存、已释放的内存、只读内存区域等)时,操作系统会触发 “Segmentation fault”,强制终止程序以保护系统内存安全。 -----产生问题的原因是:我创建一个树节点,把主函数中定的一个指针传入函数中去新建树节点

void TreeNodeCreate(TreeNode* pointer, int size)
{
    pointer = (TreeNode*)malloc(sizeof(TreeNode));
    size ++;
    pointer->left = NULL;
    pointer->right = NULL;
}

int main()
{
    int size = 0;
    TreeNode* root;
    TreeNodeCreate(root, size);

原代码的问题在于:值传递无法让函数内部的修改影响到外部变量。要正确创建树节点并更新 size,必须通过指针的指针传递节点指针,通过指针传递 size,才能实现 “修改外部变量” 的效果。 完整修改如下:

void TreeNodeCreate(TreeNode** pointer, int* size)//传入的值都是要改变的东西的地址
{
    *pointer = (TreeNode*)malloc(sizeof(TreeNode));//二级指针 加一个*是原来的一级指针
    *size ++;
    (*pointer)->left = NULL;//若不加括号,默认会被理解成*(pointer->left)
    (*pointer)->right = NULL;
}

int main()  
{
    int size = 0;
    TreeNode* root;
    TreeNodeCreate(&root, &size);//取地址传入函数内部去,这样函数内的改变才能传出来

接下来继续测试,要实现函数与外部参数同变化,是否都需要传递参数的地址进去:

void addone(int a)
{
    a++;
    return;
}

int main()
{
    int a = 0;
    addone(a);
    printf("%d", a); 
    return 0;
}

运行结果a等于0,函数内的+1并没有传递到外面 改成传入地址:

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

void addone(int* a)
{
    (*a)++;
}

int main()
{
    int a = 0;
    addone(&a);
    printf("%d", a);
    return 0;
}

这次运行结果为1,函数内的+1成功传到外面。

因此如果想用一个函数修改主函数中的值,应该把需要修改的参数取地址传入函数,而函数的传入参数值是需要改变的变量的地址,所以这个传入参数是指向变量的指针。因此改整形数据,函数参数是一级指针;改指向节点的指针,函数参数是二级指针……