0Pricing
C Academy · 课时

树节点与结构

使用指针建模节点。

树节点与结构 是 CoddyKit 上的免费 C Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C Academy 课程共包含 4 节课。

什么是二叉树

二叉树是一种层次结构,其中每个节点存储一个值,并且最多连接两个子节点:左子节点和右子节点。

位于最上方的节点是根节点。没有子节点的节点称为叶节点。这种结构非常适合快速搜索、排序和递归处理。

Node 结构体

在 C 语言中,我们使用一个结构体来表示节点,其中存储数据以及两个指向自身类型的指针。

每个指针都指向另一个 Node;如果对应方向没有子节点,则指向 NULL。

struct Node {
    int value;
    struct Node *left;
    struct Node *right;
};

为何使用自引用指针

节点不能按值包含另一个完整节点,因为这会需要无限的存储空间。相反,它会保存指向子节点的指针。

指针的大小固定,因此结构体的大小仍然是已知的,同时还可以连接到堆上的其他节点。

struct Node {
    int value;
    struct Node *left;   /* 8 bytes on 64-bit */
    struct Node *right;  /* 8 bytes on 64-bit */
};

为方便使用而定义 typedef

到处输入 struct Node 很繁琐。使用 typedef 后,我们只需写 Node。

在结构体内部仍然需要使用标签,因为此时该类型还没有完全定义。

typedef struct Node {
    int value;
    struct Node *left;
    struct Node *right;
} Node;

分配 Node

节点位于堆上,使用 malloc 创建。我们设置其值,并将两个子节点指针都初始化为 NULL。

使用这块内存之前,请始终检查 malloc 是否返回了 NULL。

Node *create_node(int value) {
    Node *n = malloc(sizeof(Node));
    if (n == NULL) return NULL;
    n->value = value;
    n->left = NULL;
    n->right = NULL;
    return n;
}

手动构建一棵小树

为了理解这些连接,请让我们手动连接三个节点:一个根节点和两个子节点。

这个程序会构建这棵树并打印各个值;在实际情况下,通常还应释放它(稍后介绍)。

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

typedef struct Node {
    int value;
    struct Node *left;
    struct Node *right;
} Node;

Node *create_node(int v) {
    Node *n = malloc(sizeof(Node));
    n->value = v; n->left = NULL; n->right = NULL;
    return n;
}

int main(void) {
    Node *root = create_node(10);
    root->left = create_node(5);
    root->right = create_node(15);
    printf("%d %d %d\n", root->left->value, root->value, root->right->value);
    return 0;
}

访问孙节点

您可以通过连续使用箭头运算符在树中导航。root->left->right 会先移动到左子节点,再移动到它的右子节点。

跟随指针之前,请确认它不是 NULL,否则程序会崩溃。

/* root
 *   \
 *    right (15)
 *        \
 *         right->right (20)
 */
if (root->right != NULL && root->right->right != NULL)
    printf("%d\n", root->right->right->value);

递归计算节点数量

递归非常适合处理树。要计算节点数量,空子树包含零个节点;否则,就将当前节点和两个子树的节点数量相加。

NULL 检查是终止递归的基本情况。

int count_nodes(Node *root) {
    if (root == NULL) return 0;
    return 1 + count_nodes(root->left)
             + count_nodes(root->right);
}

测量高度

树的高度是从根节点向下到叶节点的最长路径长度,以边数计。

我们取两个子树高度中较大的一个,再加一。空树的高度设为 -1,这样单节点树的高度就是 0。

int height(Node *root) {
    if (root == NULL) return -1;
    int l = height(root->left);
    int r = height(root->right);
    return 1 + (l > r ? l : r);
}

识别叶节点

叶节点是没有子节点的节点:left 和 right 都是 NULL。

这个小型辅助函数在许多遍历和计数过程中都很有用。

int is_leaf(Node *n) {
    return n != NULL && n->left == NULL && n->right == NULL;
}

让结构发挥作用

这里会构建一棵小树,并使用递归辅助函数报告它的节点数量和高度。

请注意,这些辅助函数从不假设固定的结构;由于递归遵循实际的指针连接,它们适用于任何树。

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

typedef struct Node { int value; struct Node *left, *right; } Node;

Node *nn(int v){ Node *n=malloc(sizeof(Node)); n->value=v; n->left=n->right=NULL; return n; }
int count(Node *r){ return r? 1+count(r->left)+count(r->right):0; }
int height(Node *r){ if(!r) return -1; int l=height(r->left),x=height(r->right); return 1+(l>x?l:x); }

int main(void){
    Node *root = nn(10);
    root->left = nn(5); root->right = nn(15);
    root->left->left = nn(2);
    printf("nodes=%d height=%d\n", count(root), height(root));
    return 0;
}

快速检查

请测试您对节点结构的理解。

回顾

二叉树节点存储一个值和两个自引用指针(left、right);没有对应子节点时,指针设为 NULL。

我们使用 malloc 分配节点,手动连接它们,并以递归方式处理它们。对于节点计数、高度计算和叶节点测试,NULL 检查始终是基本情况。

常见问题解答

「树节点与结构」课时是免费的吗?

是的 — 「树节点与结构」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C Academy 课程的其余内容,请升级到 CoddyKit PRO。 C Academy 课程共包含 4 节课。

「树节点与结构」这节课中我会学到什么?

使用指针建模节点。 你通过在浏览器中直接运行的动手代码来练习 C Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「树节点与结构」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C Academy 课中编写并运行代码吗?

能。每节 C Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 树节点与结构
  2. 向 BST 中插入
  3. 遍历
  4. 搜索与释放
← 返回 C Academy