1.树的定义
树是一种非线性的数据结构。树是由n(n>=0)个节点组成的有限集合。
如果 n=0,称为空树。
如果 n>0,则有一个称为root的节点,它只有直接后继,但没有直接前驱。
除去root外的节点分为多个互不相交的有限集合,每个集合又是一棵树,并且称为root的subtree。
2. 树家族中的概念
树的节点包含一个数据和若干指向子树的分支。
节点拥有的子树称为节点的度:
度为0的节点称为叶节点;
度不为0的称为分支节点;
树的度定义为所有节点中的度的最大值,如下图所示:
节点的直接后继称为该节点的孩子,该节点称为孩子的双亲。
节点的孩子的孩子的...称为该节点的子孙,该节点称为子孙的祖先。
同一个双亲的孩子之间相互称为兄弟,如下图所示:
节点的层次
3. 树的代码实现的实例
#include <stdio.h>
#include <stdlib.h>
// 树节点结构
typedef struct TreeNode
{
int data;
struct TreeNode* left;
struct TreeNode* right;
} TreeNode;
// 创建一个新的树节点
TreeNode* createNode(int data)
{
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
if (newNode == NULL)
{
printf("Memory allocation failed.\n");
exit(1);
}
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// 插入一个节点到树中
void insertNode(TreeNode** root, int data)
{
if (*root == NULL)
{
*root = createNode(data);
return;
}
if (data < (*root)->data)
{
insertNode(&((*root)->left), data);
}
else
{
insertNode(&((*root)->right), data);
}
}
// 先序遍历树
void preOrder(TreeNode* root)
{
if (root == NULL)
{
return;
}
printf("%d ", root->data);
preOrder(root->left);
preOrder(root->right);
}
// 中序遍历树
void inOrder(TreeNode* root)
{
if (root == NULL)
{
return;
}
inOrder(root->left);
printf("%d ", root->data);
inOrder(root->right);
}
// 后序遍历树
void postOrder(TreeNode* root)
{
if (root == NULL)
{
return;
}
postOrder(root->left);
postOrder(root->right);
printf("%d ", root->data);
}
void tree_test()
{
TreeNode* root = NULL;
// 插入节点到树中
insertNode(&root, 50);
insertNode(&root, 30);
insertNode(&root, 20);
insertNode(&root, 40);
insertNode(&root, 70);
insertNode(&root, 60);
insertNode(&root, 80);
// 先序遍历树
printf("Pre-order traversal: ");
preOrder(root);
printf("\n");
// 中序遍历树
printf("In-order traversal: ");
inOrder(root);
printf("\n");
// 后序遍历树
printf("Post-order traversal: ");
postOrder(root);
printf("\n");
}
这个示例中,我们使用C语言实现了一个简单的二叉搜索树(Binary Search Tree)。我们定义了树节点结构TreeNode
,其中包含一个整数数据data
以及左右子节点的指针。
通过createNode
函数可以创建一个新的树节点,并通过insertNode
函数将节点插入到树中。插入节点时,根据节点的值比较大小,选择合适的位置进行插入。
我们还实现了三种常见的树遍历方法:先序遍历(pre-order)、中序遍历(in-order)和后序遍历(post-order)。通过调用preOrder
、inOrder
和postOrder
函数,可以分别打印出树的节点值。
在tree_teast函数中,我们插入了一些节点,并进行了先序、中序和后序遍历的演示。