有序二叉树的递归

zxvivian 2014-01-26 10:31:22

//头文件
#ifndef __ERCHASHU_H__
#define __ERCHASHU_H__
struct node;
typedef struct tree
{
struct node *p_root;
}tree;
typedef struct node
{
int num;
// struct tree *p_left;
// struct tree *p_right;
tree left;
tree right;
}node;
void deinit(tree*);
//tree *search(tree*,int);
tree *search_new(tree*,int);
void insert_in_order(tree*,int);
int tjjd(tree*); //统计二叉树的节点数
int high(tree*);//计算二叉树的高度
#endif //__ERCHASHU_H__
//部分函数
//有序插入函数
void insert_in_order(tree *p_root,int num)
{
tree *p_tree=search_new(p_root,num);
if(!(p_tree->p_root))
{
node *p_tmp=(node*)malloc(sizeof(node));
if(p_tmp)
{
p_tmp->num=num;
p_tmp->left.p_root=NULL;
p_tmp->right.p_root=NULL;
p_tree->p_root=p_tmp;
}
}
}
//统计二叉树的节点数
int tjjd(tree *p_root)
{
int num=0;
if(!(p_root->p_root))
{
return 0;
}
num=tjjd(&(p_root->p_root->left));
num+=tjjd(&(p_root->p_root->right));
return num+1;
}
//计算二叉树的高度
int high(tree *p_root)
{
int left=0,right=0;
if(!(p_root->p_root))
{
return 0;
}
left=high(&(p_root->p_root->left));
right=high(&(p_root->p_root->right));
if(left>right||left==right)
{
return left;
}
else
{
return right;
}
}
//主函数(部分)
#include <stdio.h>
#include <stdlib.h>
#include "erchashu.h"
int main()
{
insert_in_order(&root,9);
insert_in_order(&root,5);
insert_in_order(&root,7);
insert_in_order(&root,3);
insert_in_order(&root,16);
insert_in_order(&root,8);
print(&root);
printf("\n");
printf("节点数为%d\n",tjjd(&root));
printf("树的高度为%d\n",high(&root));
}

请问为什么在计算二叉树节点数和计算二叉树高度的函数里,必须return num+1,return left+1(right+1)才能输出正确结果,没有+1就是输出的0.我一直想不明白。请高手指点迷津,并讲解一下递归函数到底是怎么样运行的(以我这个二叉树函数为例)感谢!!
...全文
65 点赞 收藏 5
写回复
5 条回复
zxvivian 2014年01月27日
引用 3 楼 ALNG 的回复:
OK 根节点问左右子树,你们各有多少节点。 左右子树又分别问他们的左右子树.... 一直到页节点。叶节点忘了算自己,说是0. 收到这个消息的上级节点,很遗憾,它的左右子树基于同样的原因都报自己高度为0,而它也不知道算上自己,还是向上级报0. 就这样一层骗一层,一直骗到档中央---根节点发现左右子树都是0个子树,忘了算自己它就把0报告给外部世界了。 高度计算的理由同此。 你用颗简单的树模拟一下就知道了。一直走到叶节点,啥都明白了。可以看出递归的总数是从一个一个1累加来的,如果把这个1换0了,多少个0相加也走不出0的黑洞。
赞~!例子生动活泼引人入胜绕梁三日不知肉味
回复 点赞
孩皮妞野 2014年01月27日
递归函数的运行有两种了解方法,一种是抽象层次上,就像数学公式一样理解。 二叉树的节点数=1. 树是空树时,为0, 否则 2. 1+左(子)数的节点数+右(子树)的节点数 你看这个公式本身就是递归的,读懂这个公式,就读懂了抽象意义上的递归。 另外一种是从特定的实现细节上理解。有点简单的汇编常识更容易明白上面的抽象的公式形成的递归函数在具体的硬件上是怎样执行的。这个你可以用一个相对简单的二叉树,单步执行跟踪一下,最好把堆栈的情形看清楚。
回复 点赞
孩皮妞野 2014年01月27日
OK 根节点问左右子树,你们各有多少节点。 左右子树又分别问他们的左右子树.... 一直到页节点。叶节点忘了算自己,说是0. 收到这个消息的上级节点,很遗憾,它的左右子树基于同样的原因都报自己高度为0,而它也不知道算上自己,还是向上级报0. 就这样一层骗一层,一直骗到档中央---根节点发现左右子树都是0个子树,忘了算自己它就把0报告给外部世界了。 高度计算的理由同此。 你用颗简单的树模拟一下就知道了。一直走到叶节点,啥都明白了。可以看出递归的总数是从一个一个1累加来的,如果把这个1换0了,多少个0相加也走不出0的黑洞。
回复 点赞
zxvivian 2014年01月27日
引用 1 楼 ALNG 的回复:
1是节点自身啊。比如根节点左子树有10个节点,右子树犹20个节点,那总结点数是不是10+20+1(自己)? 所以

int tjjd(node * n)
{
    int count;
     
    if(!n)
        return 0;
    count=1;
    if(n->left)
        count+=tjjd(n->left);
    if(n->right)
        count+=tjjd(n->right);
}

或者
int tjjd(node * n)
{
    return n==NULL?0:1+tjjd(n->left)+tjjd(n->right); 
}
高度也一样,一颗树的高度为max(左子树高度,右子树高度)+1(这个1也是根节点自身)

typedef struct node node;
#define max(a,b)  ((a)<(b)?(b):(a))

int height(node *n)
{
     return n==NULL?0:1+max(height(n->left),height(n->right));
}
这个我知道阿,为就想问为什么不加一就会输出0,不是应该就少1个节点吗
回复 点赞
孩皮妞野 2014年01月27日
1是节点自身啊。比如根节点左子树有10个节点,右子树犹20个节点,那总结点数是不是10+20+1(自己)? 所以

int tjjd(node * n)
{
    int count;
     
    if(!n)
        return 0;
    count=1;
    if(n->left)
        count+=tjjd(n->left);
    if(n->right)
        count+=tjjd(n->right);
}

或者
int tjjd(node * n)
{
    return n==NULL?0:1+tjjd(n->left)+tjjd(n->right); 
}
高度也一样,一颗树的高度为max(左子树高度,右子树高度)+1(这个1也是根节点自身)

typedef struct node node;
#define max(a,b)  ((a)<(b)?(b):(a))

int height(node *n)
{
     return n==NULL?0:1+max(height(n->left),height(n->right));
}
回复 点赞
发动态
发帖子
C语言
创建于2007-09-28

3.2w+

社区成员

24.0w+

社区内容

C语言相关问题讨论
社区公告
暂无公告