C语言实现二叉树-03版
我们亲爱的项目经理真是有创意,他说你给我写得二叉树挺好的;
功能还算可以:插入节点,能够删除节点;
可是有时候我们只是需要查找树的某个节点是否存在;
所以我希望你能够给我一个find功能;
还有就是,我在跟BOSS交流的时候,他根本不相信你已经把链表写成树的结构啦;
他希望你能够更明显的把树的结构打印出来;
所以,你需要实现一个show功能;
这应该不难吧;
Problem
我们需要实现的其实是遍历的两个变体;
首先确定我们的思路,想到都是需要遍历的;
那么我们是不是又想到了有递归的方式和非递归的方式呢;
- int find_recursive(Node *root, int data)
- {
- //TODO
- }
我们首先实现的是递归的,大致的结构应该是这样的;
还记得吗?递归的前面几行一般是递归的结束条件;
因此,我们的代码应该是这样的:
- int find_recursive(Node *root, int data)
- {
- if(root == NULL)
- return ;
- }
其次,我们应当考虑找到目标的时候,应该是怎么确定的呢?
应该是root->data 与参数data相等的时候,我们希望程序返回啦;
因此,我们需要的代码可能会是这样的;
- int find_recursive(Node *root, int data)
- {
- if(root == NULL){
- return ;
- }else if(root->data == data){
- return ;
- }
- }
那,在当前的节点上如果没有找到目标呢;
我们需要的应该是确定往左找还是往右找;
所以需要把代码写成如下的形式;
- int find_recursive(Node *root, int data)
- {
- if(root == NULL){
- return ;
- }else if(root->data == data){
- return ;
- }else{
- int dir = root->data < data;
- return find_recursive(root->link[dir],data);
- }
- }
dir的值只能是0或者1,代表的意义是什么大家应该很清楚啦;
它的作用是什么也应该很清楚啦;
最后执行递归;
通常我们需要客户操作的是树,因此我们需要一个包装函数;
- int find(Tree *tree,int data)
- {
- return find_recursive(tree->root,data);
- }
好啦,我们可以测试一下啦;
我首先把需要用到得代码附上;
- #include <stdio.h>
#include <stdlib.h>- #include <time.h>
- typedef struct _node {
- int data;
- struct _node *link[];
- }Node;
- typedef struct _tree{
- struct _node *root;
- }Tree;
- Tree * init_tree()
- {
- Tree *temp = (Tree*)malloc(sizeof(Tree));
- temp->root = NULL;
- return temp;
- }
- Node * make_node(int data)
- {
- Node *temp = (Node*)malloc(sizeof(Node));
- temp->link[] = temp->link[] = NULL;
- temp->data = data;
- return temp;
- }
- int insert(Tree *tree, int data)
- {
- if(tree->root == NULL){
- tree->root = make_node(data);
- }else{
- Node * it = tree->root;
- int dir ;
- for(;;){
- dir = it->data < data;
- if(it->data == data){
- return ;
- }else if(it->link[dir] == NULL){
- break;
- }
- it = it->link[dir];
- }
- it->link[dir] = make_node(data);
- }
- return ;
- }
测试主函数代码如下:
- int main(void)
- {
- Tree * tree = init_tree();
- insert(tree,);
- insert(tree,);
- insert(tree,);
- insert(tree,);
- printf("looking for %d...%s\n",,find(tree,) ? "Got it":"Not exist");
- printf("looking for %d...%s\n",,find(tree,) ? "Got it":"Not exist");
- return ;
- }
运行结果如下:
好啦!可能对于客户来说,这样把查询的数据写死啦,并把那么好;
别人可能想查某个数据就输入某个数据,可能更实用;
这是非常简单的功能,我不会去讲解,但是也附上一份简单的实现;
大家写的肯的能够更加漂亮;
- void tips(){
- time_t curTime;
- struct tm *ts;
- time_t testTime = time(&curTime);
- ts = localtime(&curTime);
- //struct tm *tsgm = gmtime(&curTime);
- puts("*************************************************************");
- printf("Date:%s",asctime(ts));
- puts("Please input right cmd");
- puts("1)Search");
- puts("2)Quit");
- puts("*************************************************************");
- }
- int search(Tree *tree)
- {
- char cmd;
- int isExist;
- int target;
- tips();
- while((cmd=getchar())!=EOF){
- if(cmd==''){
- puts("-------------------------------------------------------------");
- printf("Please input the target:");
- scanf("%d",&target);
- isExist=find(tree,target);
- if(isExist){
- printf("Target %d is exists \n",target);
- puts("-------------------------------------------------------------");
- puts("\n");
- continue;
- //break;
- }else{
- puts("Target Not exitst");
- puts("-------------------------------------------------------------");
- puts("\n");
- continue;
- //break;
- }
- }else if(cmd==''){
- puts("bye~");
- break;
- }else{
- tips();
- }
- }
- return ;
- }
运行结果如下:
这个可能用户体验要较好些;
注意别忘记包涵头文件time.h
好啦查询工作算是完成啦;
接下来是下一个任务;
Problem
为啦更加形象的表明我们一直在写得是一棵树;
我想有必要show也就是秀秀我们的成果啦;
这次咱们先看要实现的效果,如下图;
我们的树根就是8,而~符合代表就是叶子啦;
这样旋转90°的树可能你不一定喜欢;
但是,如果你想再旋转90度的话你就自己想想吧;
好啦,接下来就是实现啦;
不管它咱们显示,咱们始终记住,我们需要遍历;
为简单,我们使用递归实现;
- void structure_recursive(Node *root,int level)
- {
- if(root == NULL){
- //TODO
- }else{
- //TODO;
- }
- }
这个遍历方式结构就怎么简单;
但是请思考思考,我们的输出到终端上得数据是先大的,然后是小的;
显然是只有中序遍历才能得到按正确的大小顺序输出;
所以我们需要记住这点哈;
- void structure_recursive(Node *root,int level)
- {
- if(root == NULL){
- //TODO
- }else{
- structure_recursive(root->link[],level + );
- printf("%d\n",root->data);
- structure_recursive(root->link[],level + );
- }
- }
你会发现,我首先写else部分,仔细看看else部分你会发现我们的中序遍历很明显啦;
可是呢!!它又有别于我们前面写得中序遍历方式,我们首先从右子树下手啦;
以前都是从左子树的,这就是为什么我们输出的结果是从大到小往下的啦;
好啦!TODO到底应该写成什么样子呢?
想想要是我们一直递归到最后要是递归一次我们就得增加一个level的计数;
到最后发现叶子是NULL我们就直接输出level个tab然后跟一个~表示叶子;
所以代码如下:
- void structure_recursive(Node *root,int level)
- {
int i;- if(root == NULL){
- for(i = ;i<level;i++){
- putchar('\t');
- }
- puts("~");
- }else{
- structure_recursive(root->link[],level + );
- printf("%d\n",root->data);
- structure_recursive(root->link[],level + );
- }
- }
这里已经差不多完事啦,但是我们先去写一个包装函数;
- void structure(Tree *tree)
- {
- structure_recursive(tree->root,);
- }
注意包装函数里面的0表示是从最左边开始打印的;
我们先不去完善我们的structure_recursive函数,我们直接测试,看看结果;
这个可不是我们想看到的结果哈;
原因是什么呢;
我们还没有完善我们的函数呢;
- void structure_recursive(Node *root,int level)
- {
- int i;
- if(root == NULL){
- for(i = ;i<level;i++){
- putchar('\t');
- }
- puts("~");
- }else{
- structure_recursive(root->link[],level + );
- for(i = ;i < level;i++){
- putchar('\t');
- }
- printf("%d\n",root->data);
- structure_recursive(root->link[],level + );
- }
- }
好啦,我们的效果出来啦;
好啦!工作完成啦;
总结一下吧;
不,还没有到总结的时候;
明天的任务还有呢:
我们的树不能一直老想着用递归实现,在很多时候它是受限制的;
递归对空间要求特别多,所以我们下次想想有没有非递归的方法实现其他的函数;
最后附上我们今天所有代码吧:
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- typedef struct _node {
- int data;
- struct _node *link[];
- }Node;
- typedef struct _tree{
- struct _node *root;
- }Tree;
- Tree * init_tree()
- {
- Tree *temp = (Tree*)malloc(sizeof(Tree));
- temp->root = NULL;
- return temp;
- }
- Node * make_node(int data)
- {
- Node *temp = (Node*)malloc(sizeof(Node));
- temp->link[] = temp->link[] = NULL;
- temp->data = data;
- return temp;
- }
- int insert(Tree *tree, int data)
- {
- if(tree->root == NULL){
- tree->root = make_node(data);
- }else{
- Node * it = tree->root;
- int dir ;
- for(;;){
- dir = it->data < data;
- if(it->data == data){
- return ;
- }else if(it->link[dir] == NULL){
- break;
- }
- it = it->link[dir];
- }
- it->link[dir] = make_node(data);
- }
- return ;
- }
- int remove_node(Tree *tree, int data)
- {
- if(tree->root != NULL)
- {
- Node *p = NULL;
- Node *succ;
- Node *it = tree->root;
- int dir;
- for(;;){
- if( it == NULL){
- return ;
- }else if(it->data == data){
- break;
- }
- dir = it->data < data;
- p = it;
- it = it->link[dir];
- }
- /***********************************************************************/
- if(it->link[] != NULL && it->link[] != NULL){
- p = it;
- succ = it->link[];
- while(succ->link[] != NULL){
- p = succ;
- succ = succ->link[];
- }
- it->data = succ->data;
- p->link[p->link[] == succ] = succ->link[];
- free(succ);
- /***********************************************************************/
- }else{ /*it->link[0] == NULL || it->link[1] == NULL */
- dir = it->link[] == NULL;
- if( p == NULL){
- tree->root = it->link[dir];
- }else{
- p->link[p->link[] == it] = it->link[dir];
- }
- free(it);
- }
- }
- return ;
- }
- int find_recursive(Node *root, int data)
- {
- if(root == NULL){
- return ;
- }else if(root->data == data){
- return ;
- }else{
- int dir = root->data < data;
- return find_recursive(root->link[dir],data);
- }
- }
- int find(Tree *tree,int data)
- {
- return find_recursive(tree->root,data);
- }
- void tips(){
- time_t curTime;
- struct tm *ts;
- time_t testTime = time(&curTime);
- ts = localtime(&curTime);
- //struct tm *tsgm = gmtime(&curTime);
- puts("*************************************************************");
- printf("Date:%s",asctime(ts));
- puts("Please input right cmd");
- puts("1)Search");
- puts("2)Quit");
- puts("*************************************************************");
- }
- int search(Tree *tree)
- {
- char cmd;
- int isExist;
- int target;
- tips();
- while((cmd=getchar())!=EOF){
- if(cmd==''){
- puts("-------------------------------------------------------------");
- printf("Please input the target:");
- scanf("%d",&target);
- isExist=find(tree,target);
- if(isExist){
- printf("Target %d is exists \n",target);
- puts("-------------------------------------------------------------");
- puts("\n");
- continue;
- //break;
- }else{
- puts("Target Not exitst");
- puts("-------------------------------------------------------------");
- puts("\n");
- continue;
- //break;
- }
- }else if(cmd==''){
- puts("bye~");
- break;
- }else{
- tips();
- }
- }
- return ;
- }
- void structure_recursive(Node *root,int level)
- {
- int i;
- if(root == NULL){
- for(i = ;i<level;i++){
- putchar('\t');
- }
- puts("~");
- }else{
- structure_recursive(root->link[],level + );
- for(i = ;i < level;i++){
- putchar('\t');
- }
- printf("%d\n",root->data);
- structure_recursive(root->link[],level + );
- }
- }
- void structure_recursive(Node *root,int level)
- {
- int i;
- if(root == NULL){
- for(i = ;i<level;i++){
- putchar('\t');
- }
- puts("~");
- }else{
- structure_recursive(root->link[],level + );
- for(i = ;i < level;i++){
- putchar('\t');
- }
- printf("%d\n",root->data);
- structure_recursive(root->link[],level + );
- }
- }
- void structure(Tree *tree)
- {
- structure_recursive(tree->root,);
- }
- int main(void)
- {
- Tree * tree = init_tree();
- insert(tree,);
- insert(tree,);
- insert(tree,);
- insert(tree,);
- insert(tree,);
- insert(tree,);
- structure(tree);
- return ;
- }
C语言实现二叉树-03版的更多相关文章
- C语言实现二叉树-02版
---恢复内容开始--- 昨天,提交完我们的二叉树项目后,今天早上项目经理早早给我打电话: 他说,小伙子干的不错.但是为什么你上面的insert是recusive的呢? 你难道不知道万一数据量大啦!那 ...
- C语言实现二叉树-04版
二叉树,通常应当是研究其他一些复杂的数据结构的基础.因此,通常我们应该精通它,而不是了解:当然,可能并不是每个人都认同这种观点,甚至有些人认为理解数据结构就行了!根本没有必要去研究如何实现,因为大多数 ...
- C语言实现二叉树-01版
故事是这样开始的,项目经理有一天终于还是拍拍我肩膀说: 无论你的链表写得多么的好,无论是多么的灵活,我也得费老半天才查找到想要的数据: 这让我的工作非常苦恼,听说有一种叫做二叉树的数据结构,你看能不能 ...
- 数据结构与抽象 Java语言描述 第4版 pdf (内含标签)
数据结构与抽象 Java语言描述 第4版 目录 前言引言组织数据序言设计类P.1封装P.2说明方法P.2.1注释P.2.2前置条件和后置条件P.2.3断言P.3Java接口P.3.1写一个接口P.3. ...
- C语言实现二叉树-利用二叉树统计单词数目
昨天刚参加了腾讯2015年在线模拟考: 四道大题的第一题就是单词统计程序的设计思想: 为了记住这一天,我打算今天通过代码实现一下: 我将用到的核心数据结构是二叉树: (要是想了解简单二叉树的实现,可以 ...
- 《C++程序设计语言(英文第四版)》【PDF】下载
<C++程序设计语言(英文第四版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382177 内容简介 本书是C++领域经典的参 ...
- Rust语言之HelloWorld Web版
Rust语言之HelloWorld Web版 下面这篇文章值得仔细研读: http://arthurtw.github.io/2014/12/21/rust-anti-sloppy-programmi ...
- | C语言I作业03
| C语言I作业03 标签: 18软件 李煦亮 问题 答案 这个作业属于那个课程 C语言程序设计I 这个作业要求在哪里 https://edu.cnblogs.com 我在这个课程的目标是 学会和掌握 ...
- R语言实战(第二版)-part 1笔记
说明: 1.本笔记对<R语言实战>一书有选择性的进行记录,仅用于个人的查漏补缺 2.将完全掌握的以及无实战需求的知识点略去 3.代码直接在Rsudio中运行学习 R语言实战(第二版) pa ...
随机推荐
- 处理BOM
[处理BOM]
- php 学习使用
https://netbeans.org/kb/docs/php/wish-list-lesson1_zh_CN.html#register-mysql http://www.php100.com/h ...
- jQuery的append和appendTo
这两个关键词,Insus.NET刚开始学习jQuery时,也被它弄得不好理解.现用得多了,运行与理解也不难了. 查了英文词典append的意思是“添加,附加”: 而后者appendTo意思是“ 添加至 ...
- 使用 RecyclerView
使用 RecyclerView android RecyclerView tutorial 概述 与 ListView 的对比 RecyclerView 的组件 LayoutManager Recyc ...
- C# 程序间通信的各种途径及解析
一.开篇 程序间通信的主要目的是实现多台计算机(也可以是同一台)中应用程序之间的数据共享与信息交换.在不同的计算机系统中,它们之间要通过网络之间的协议才能 实现数据共享与信息交换:在同一台计算机系统中 ...
- [刘阳Java]_Java程序员的成长路线_第3讲
按照Java从业人员的职位晋升来说,Java程序成长路线大致如下 Java程序员 JavaEE初级软件工程师 JavaEE中级软件工程师 JavaEE高级软件工程师 Java架构师 按照职业发展方向, ...
- js 运算符优先级
在看jquery源码,仔细看入口函数的时候,有点懵了.看到与或.多重三目,傻傻的分不清,就代码仔细的区分下运算符优先级,以前都是呼呼的飘过.看来任何一个细节都不能忽略,不然效率极低.. !functi ...
- protocol buffers的使用示例[z]
[http://blog.csdn.net/zhu_xun/article/details/19397081] protocol buffers的使用示例 如果不了解protocol buffers, ...
- Samba服务器搭建配置
本次环境: 服务端-centos6.8-192.168.2.200 客户端1-centos6.8-192.168.2.201 客户端2-Windows7-192.168.2.104 假设条件如下: 使 ...
- Having关键字
Having关键字:用于对整组整组地过滤(对比,where仅仅是一行一行地过滤.) 查询每个住址各住多少人? 查询住址的会员人数超过2人的住址. 注意,出现顺序where>group by> ...