经过两天半的写写画画,终于把树的储存结构中求得树的最大高度的递归算法弄懂了,是的,只是求最大高度的算法,其他输出树以及创造树的函数还没搞明白,数据结构的两个槛果然是链表和树,感觉自己真的不适合搞算法。
下面分享一下这次学习的一些感想吧,主要有两个部分:
(1) 树的最大高度算法的理解
(2) 为什么算法的设计是先查找下指针后查找右指针而不是先右后下
----------------------------------------------------------------------------
首先第一个问题,树的最大高度的算法如下:
int TreeHeight(TSBNode *t)
{
TSBNode *p;
int m, max = 0;
if (t == NULL)
return(0);
else if (t->vp == NULL)
return(1);
else
{
//求t的子树的最大高度max
p = t->vp;
while (p != NULL)
{
m = TreeHeight(p);
if (max<m)
max = m;
p = p->hp;
}
return(max + 1);
}
}
返回值为树的最大高度,其实这个算法的难点就在于递归,如果只是单纯的递归其实可以一层层的推出来的,但是这个递归不一样,我们可以把进入一次函数理解为进入一个节点也就是说在递归时,我将经过这个函数,但是我发现凡是向右并且不向下的节点都会立刻退出进入的函数,也就意味着向右且不向下的节点被淘汰了,不会参与到递归之中,最终的结果就是树中会形成想电梯一样的一竖条节点直接一层层向上递归,这样很大的节省了时间。
关于树的最大高度,它的得出是需要一个数据来记录的,在子树的分支处,也要比较两个子树的高度并储存较大值,所以有所比较,其实不难发现,在树的自上而下的遍历时,由于不断的进入函数,由语句int m, max = 0;可知,max一直被设置为0,所以此时max并没有起到计数的作用,直到树自下向上递归时,max才由一次次返回计数,对于树的分支情况,由于从一个分支到另一个分支要进入一次函数,又会引发一次自上而下的针对分支子树的遍历,所以max还会为0,最终,在分支会和处,前分支的值已储存在max中,后分支的m将返回并比较,所以得到的会是较大值。
还有一个疑点就在于为什么下指针为NULL且由指针为NULL时会连续两次返回(max+1),其实这并不会造成错误,因为自下向上的递归中会返回树高-1次,所以这么写算法没有什么影响,仍然会得到正确的结果。
-------------------------------------------------------------------------
然后是第二个问题,关于算法设计时为什么是先查找下指针后查找右指针而不是先右后下,下面是这次树算法的结构组成:
typedef struct tnode
{
ElemType data; //节点的值
struct tnode *hp; //指向兄弟
struct tnode *vp; //指向孩子节点
} TSBNode;
因为树的结构和节点设计所致,只会有两种算法思路,也就是先下后右或者先右后下,其实先右后下是行不通的,因为先右后下的结果就是在向右时需要丢弃节点,但是一旦丢弃节点,如果节点有向下的指针,那么算法就不可能遍历整个树,何谈求出正确的最大树高呢?
----------------------------------------------------------------
就是这些了,数据结构真的不算简单,所以看到立在书架上的算法导论别提有多绝望了,哎,加油吧!