C语言实现二叉树
二叉树的重要性就不用多说啦;
我以前也学习过,但是一直没有总结;
网上找到的例子,要么是理论一大堆,然后是伪代码实现;
要么是复杂的代码,没有什么解释;
最终,还是靠翻墙找到一些好的文章,参考地址我会在See Also部分给大家贴出来
Problem
假设我们要生成的二叉树如下图;
Solution
显然,我们需要在节点保存的数据只有一个整数;
struct binary_tree {
int data ; // Data area
//TODO
};
所以在结构体里面,我们的代码应该类似上面的写法;
通过观察我们还发现,每一个节点都指向左右两边(除了最后的叶子节点外);
因此,我们需要让它有两个指针域;
可能你会想到类似如下的写法;
struct binary_tree {
int data ; // Data area
void * left;
void * right;
};
上面的定义格式似乎是正确的,但是类型好像并不是我们想要的;
例如:当left指向左边的子节点时,子节点应该也是一个包涵数据域的节点;
因此我们需要再定义一个与它本身相同的结构体;
struct binary_tree {
int data ; // Data area
struct binary_tree * left;
struct binary_tree * right;
};
所以,我们会这样去定义它;
显然,这是一个递归定义;
如果我们要实例化一个节点,我们可以:
struct binary_tree * tree;
显然我们需要定义一个实例写那么长的类型名字,实在让人难受;
因此,我们可以这样;
typedef struct binary_tree node;
node * tree;
好啦!到此为止我们的数据域就定义好啦!你现在的代码应该是下面的样子啦;
struct binary_tree {
int data ; // Data area
binary_tree * left;
binary_tree * right;
}; typedef struct binary_tree node;
接下来我们需要把数据插入到对应的位置上;
我们希望树左边分支的的数据总是比树右边分支的要小;
至于为什么我们暂时不解释;
void insert(node ** tree, int val) {
node * temp = NULL;
if(!(*tree)) {
//TODO
return ;
} if (val < (*tree)->data) {
//TODO
}else if (val > (*tree)->data) {
//TODO
}
}
因此我们代码会像上面这样写;
第一个if语句判断这个树节点是否存在;
若是不存在,我们应该生成一个节点,然后添加到树上来;
第二个if-else呢,则是判断这个给定要存入的数据是大于当前节点的呢还是小于;
小于呢,存在左分支。大于存在右分支;
if(!(*tree)) {
temp = (node *)malloc(sizeof(node));
temp->left = temp->right = NULL;
temp->data = val;
*tree = temp;
return ;
}
分析上面代码片段,我们发现temp的作用是临时变量正如其名;
malloc分配内存,然后初始化节点左右指针域为空,以及数据域为val;
最后*tree=temp 把节点安装到树上;
并且返回上一级;
对于已经存在的树节点,我们需要往左右两分子扩展;
因此我们的代码会是这样的;
if (val < (*tree)->data) {
insert(&(*tree)->left,val);
}else if (val > (*tree)->data) {
insert(&(*tree)->right,val);
}
从代码中可以看出,只对小于和大于两个方向的数据进行操作;
你也许会考虑到万一等于呢。
注意,在这里应该是数据的唯一性有要求的,它类似于数学里的集合,不会有重复的;
它的这种特性对我们往后要写得单词统计程序非常有帮助;
那么这个函数的所有代码如下:
void insert(node ** tree, int val) {
node * temp = NULL;
if(!(*tree)) {
temp = (node *)malloc(sizeof(node));
temp->left = temp->right = NULL;
temp->data = val;
*tree = temp;
return ;
} if (val < (*tree)->data) {
insert(&(*tree)->left,val);
}else if (val > (*tree)->data) {
insert(&(*tree)->right,val);
}
}
节点创建好了,注意我们用malloc创建;
因此,我们是在堆中分配的内存,因此我们需要手动释放;
那显然需要用到free函数与之对应;
所以我们释放节点的函数应该是这样的;
void deltree(node * tree) {
if(tree) {
free(tree);
}
}
这样似乎也没有问题啦!但是仔细观察我们发现;
直接释放啦free就只是释放啦根节点;
就好比,我们去拔花生;我们只是简单的用剪刀把上面的叶子剪断啦;
没有想过把花生沿着根一直挖下去是不可能把所有花生弄出来的;
因此,我们需要这样做;
void deltree(node * tree) {
if(tree) {
deltree(tree->left);
deltree(tree->right);
free(tree);
}
}
这样我们找到左边的根啦,又继续往左边找;
找不到啦,就往右边找;
再找不到啦,就执行到free释放节点然后返回上一级;
好啦!树也有函数建啦,也有办法“砍”啦!
接下来是怎么展示我们的树啦;
树的遍历有三种;
前,中,后;
void print_preorder(node * tree) {
if(tree) {
//TODO }
}
首先我们需要判断tree是否空;
要是空的,我们就没有必要看里面还有什么数据啦;
void print_preorder(node * tree) {
if(tree) {
printf("%d\n",tree->data);
print_preorder(tree->left);
print_preorder(tree->right);
}
}
同样的我们把中序和后序写出来;
void print_preorder(node * tree) {
if(tree) {
printf("%d\n",tree->data);
print_preorder(tree->left);
print_preorder(tree->right);
}
} void print_inorder(node * tree) {
if(tree) {
print_inorder(tree->left);
printf("%d\n",tree->data);
print_inorder(tree->right);
}
} void print_postorder(node * tree) {
if(tree) {
print_postorder(tree->left);
print_postorder(tree->right);
printf("%d\n",tree->data);
}
}
好啦!该有的函数都有啦;
我们该写测试函数啦;
int main(void)
{
node * root;
node * tmp;
//int i; root = NULL;
/* Inserting nodes into tree */
insert(&root,);
insert(&root,);
insert(&root,);
insert(&root,);
insert(&root,);
insert(&root,);
insert(&root,); printf("Pre Order Display\n");
print_preorder(root); printf("In Order Display\n");
print_inorder(root); printf("Post Order Display\n");
print_postorder(root); /* Deleting all nodes of tree */
deltree(root);
}
运行结果如下:
Pre Order Display In Order Display Post Order Display
Discussion
然后这个例子似乎太简单了!它没有对树进行查询的函数;
也没有树的高度进行测量;
但是,它的简洁是为了更加容易理解;
可是呢!太简洁了,以至于我们都不知道为什么要把数据弄成树形结构;
为什么,难道线性结构的数据还不能解决我们身边的问题吗?
这个问题,不知道大家有没有问过自己。反正我以前经常问自己;
那么,为了让大家理解存在树形结构的数据的必要性;
我们,设想要统计C语言的关键字在代码中出现的频率;
我们会怎么做呢??(这个问题我会在另一篇文章讲解)
See Alson
http://www.thegeekstuff.com/2013/02/c-binary-tree/
C语言实现二叉树的更多相关文章
- C语言实现二叉树-02版
---恢复内容开始--- 昨天,提交完我们的二叉树项目后,今天早上项目经理早早给我打电话: 他说,小伙子干的不错.但是为什么你上面的insert是recusive的呢? 你难道不知道万一数据量大啦!那 ...
- C语言实现二叉树-利用二叉树统计单词数目
昨天刚参加了腾讯2015年在线模拟考: 四道大题的第一题就是单词统计程序的设计思想: 为了记住这一天,我打算今天通过代码实现一下: 我将用到的核心数据结构是二叉树: (要是想了解简单二叉树的实现,可以 ...
- C语言实现二叉树的基本操作
二叉树是一种非常重要的数据结构.本文总结了二叉树的常见操作:二叉树的构建,查找,删除,二叉树的遍历(包括前序遍历.中序遍历.后序遍历.层次遍历),二叉搜索树的构造等. 1. 二叉树的构建 二叉树的基本 ...
- C语言描述二叉树的实现及操作(链表实现)
概述 二叉树为每个节点最多有两个儿子节点(左儿子节点和右儿子节点)的树. 前序遍历:根结点 ---> 左子树 ---> 右子树. 中序遍历:左子树---> 根结点 ---&g ...
- C语言数据库-二叉树
一.定义 二叉树在图论中是这样定义的:二叉树是一个连通的无环图,并且每一个顶点的度不大于3.有根二叉树还要满足根结点的度不大于2.有了根结点之后,每个顶点定义了唯一的父结点,和最多2个子结点.然而,没 ...
- go语言浅析二叉树
Hello,各位小伙伴大家好,我是小栈君,今天给大家带来的分享是关于关于二叉树相关的知识点,并用go语言实现一个二叉树和对二叉树进行遍历. 我们主要针对二叉树的概念,go实战实现二叉树的前序遍历.中序 ...
- c语言_二叉树的建立以及3种递归
二叉树c语言的实现 二叉树的建立 二叉树的数据结构 typedef struct node{ int data; struct node* left; struct node* ri ...
- C语言实现二叉树-04版
二叉树,通常应当是研究其他一些复杂的数据结构的基础.因此,通常我们应该精通它,而不是了解:当然,可能并不是每个人都认同这种观点,甚至有些人认为理解数据结构就行了!根本没有必要去研究如何实现,因为大多数 ...
- C语言实现二叉树-03版
我们亲爱的项目经理真是有创意,他说你给我写得二叉树挺好的: 功能还算可以:插入节点,能够删除节点: 可是有时候我们只是需要查找树的某个节点是否存在: 所以我希望你能够给我一个find功能: 还有就是, ...
随机推荐
- git撤销commit
请参考该文章:http://www.cnblogs.com/ningkyolei/p/5026011.html 场景: 不小心commit了一个不应该commit的修改,但是还没有push,想撤销那个 ...
- NLPP-03-Exercises
<PYTHON自然语言处理>第3章 处理原始文本 更多更复杂有关处理HTML内容 http://www.crummy.com/software/BeautifulSoup/ 3.11 深入 ...
- android项目中使用开源数据库litepal
下载地址 https://github.com/LitePalFramework/LitePal 参考文档 http://blog.csdn.net/guolin_blog/article/detai ...
- 技术英文单词贴--P
P pagination 分页,页码 parse 解析,从语法上描述或分析 partial 局部的 pattern 模式 populate 填充,居住于,构成人口 precedence 优先 pref ...
- Asp.net web api部署在某些服务器上老是404
asp.net web api部署在Windows服务器上后,按照WebAPI定义的路由访问,老是出现404,但定义一个静态文件从站点访问,却又OK. 这时,便可以确定是WebAPI路由出了问题,经调 ...
- 存在网路的情况下重命名SDE中数据图层错误(The orphan junction feature class cannot be renamed)
运行环境为ArcGIS9.3,VS2008. 问题描述:数据通过SDE存储在Oracle10g数据库中,数据集中存在几何网络,在存在网络的情况下通过程序对其中的数据图层进行重命名,弹出"Th ...
- javascript 封装分页
最近自己做了一个后台,想把分页通过js给封装起来 于是乎就有了下面的代码 此代码,算是一个半成品,还需完善,思路还是可以借鉴的 page方法传入3个参数 1.total总条数 2.page当前页码 3 ...
- NSDate获取当前时间,并且转化为需要的格式
NSDate *date = [NSDate date]; NSDateFormatter *formatter = [[NSDateFormatter alloc]init]; [formatter ...
- 咏南中间件+开发框架支持最新的DELPHI XE10.1(BERLIN) UPDATE1
咏南中间件+开发框架支持最新的DELPHI XE10.1(BERLIN) UPDATE1 购买提供:中间件源码,价格十分优惠!有意者请向本人索取演示程序! 附带福利(赠送): CS开发框架源码BS开发 ...
- 一些有意思的APP
1.简书:一个优雅的写作/阅读平台. 2.知乎:知识分享社区: 3.behance:设计者的圈子: 4.海词词典:电脑.手机同步查询的好帮手(电脑端快捷键:双击 Alt 弹出/关闭查询框,非常方便) ...