C语言实现树,你一定看得懂

之前写了好多篇文章关于数据结构的,既然讲到了数据结构,那么就必须要说一下树,树这个数据结构使用范围非常广,应用前景广阔。

关联文章:

五分钟搞懂什么是红黑树(全程图解)

Linux 内核红黑树分析

这篇文章主要是讲解最简单的一个树的构成,并用代码实现。

声明节点结构体

/*树节点*/
typedef struct node{
int data;
struct node * left; /*节点左边的树枝*/
struct node * right;/*节点右边的树枝*/
}Node;

data 是这个节点的数据,left是这个节点指向左边节点的指针,right 是指向右边节点的指针。

声明根节点结构体

/*树根*/
typedef struct tree{
Node * root;
}Tree;

根节点也是一个节点,只不过这个节点代表了这棵树,这个节点存在,就代表这棵树没有死。

定义一个根节点

	Tree tree;
tree.root = NULL;/*创建一个空树*/

像节点插入一个数据

我们现在模拟一下,插入一个数据 5

/*插入函数 向一个树里面插入数据*/
void insert(Tree* tree, int value)
{
/*创建一个节点*/
Node* node=(Node*)malloc(sizeof(Node));
node->data = value;
node->left = NULL;
node->right = NULL;

/*判断树是不是空树*/
if (tree->root == NULL)
{
tree->root = node;
}
//.......
}

我们会先判断 这个树是不是空的,如果是空的,就把这树根指向这个 node 节点。

我们再插入一个数据 4

因为 4 小于 5,所以我们需要把 4插入到 5 的左边节点去。

insert(&tree, temp);

所以就变成这样

我们再插入一个数据 3

因为 3 小于 4,那我们就再插入到4的left节点。

如果我们再插入一个 5呢?

大于等于 当前节点的,都进入right节点,所以,插入 5 会变成这样。

遍历一棵树

遍历一棵树的方法有很多,前序遍历,中序遍历,后序遍历,我这里就不说了,无非就是递归判断节点是否为空,我这里使用的是中序遍历。

/*
遍历一整颗树
中序遍历:先左后根再右
*/
void traverse(Node* node)
{
if(node != NULL)
{
traverse(node->left);
printf("%d ",node->data);
traverse(node->right);
}
}

traverse(node->left); 递归扫描所有的左子树节点 traverse(node->right); 递归扫描所有的右子树节点

销毁一棵树

既然我们是通过 malloc 来创建一棵树的,那么使用完后,肯定需要释放内存,要不然内存就会一直消耗占用。

/*销毁一棵树*/
void distory_tree(Node* node)
{

if(node != NULL)
{
distory_tree(node->left);
distory_tree(node->right);
printf("free node:%d\n",node->data);
free(node);
node = NULL;
}
}

使用递归很爽啊,一直使用一直爽啊。哈哈,那就一直使用递归好了。

完整代码

#include "stdio.h"
#include "stdlib.h"

/*树节点*/
typedef struct node{
int data;
struct node * left; /*节点左边的树枝*/
struct node * right;/*节点右边的树枝*/
}Node;

/*树根*/
typedef struct tree{
Node * root;
}Tree;

/*插入函数 向一个树里面插入数据*/
void insert(Tree* tree, int value)
{
/*创建一个节点*/
Node* node=(Node*)malloc(sizeof(Node));
node->data = value;
node->left = NULL;
node->right = NULL;

/*判断树是不是空树*/
if (tree->root == NULL)
{
tree->root = node;
}
else /*不是空树*/
{
Node* temp = tree->root;/*从树根开始*/
while (temp != NULL)
{
if(value < temp->data)/*小于就进左儿子*/
{
if(temp->left == NULL)
{
temp->left = node;
return;
}
else /*继续判断*/
{
temp = temp->left;
}
}
else /*否则进右儿子*/
{

if(temp->right == NULL)
{
temp->right = node;
return;
}
else /*继续判断*/
{
temp = temp->right;
}
}
}
}
}

/*
遍历一整颗树
中序遍历:先左后根再右
*/
void traverse(Node* node)
{
if(node != NULL)
{
traverse(node->left);
printf("%d ",node->data);
traverse(node->right);
}
}

/*销毁一棵树*/
void distory_tree(Node* node)
{

if(node != NULL)
{
distory_tree(node->left);
distory_tree(node->right);
printf("free node:%d\n",node->data);
free(node);
node = NULL;
}
}

/*主函数*/
int main()
{
int i = 0;
Tree tree;
tree.root = NULL;/*创建一个空树*/
int n;
printf("input total num:\n");
/*输入n个数并创建这个树*/
scanf("%d",&n);
for(i = 0; i < n; i++)
{
int temp;
scanf("%d",&temp);
insert(&tree, temp);
}
/*遍历整个树*/
traverse(tree.root);

/*销毁一棵树*/
distory_tree(tree.root);
return 0;
}

总结

数据结构里的树是一个难点和重点,变化也非常多,我们安卓系统里面的跨进程间通信,使用的binder,底层就是有使用到红黑树,大家如果通过这个小例子知道树这个概念,以后遇到就不至于一愣一愣的。

好吧,就说这么多,文章有问题的,欢迎批评指正,我们要在批评与指正中成长,觉得不错的,感谢转发和再看。

共勉~

—————END—————

扫码或长按关注
回复「  加群  」进入技术群聊

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值