线索二叉树小记

首先,是这个玩意能干嘛用。

树有三种遍历的方法

1,先序(根左右)

2,中序(左根右)

3,后序(左右根)

每一种遍历过后都会产生一个遍历序列,该序列中某一个节点n在各个遍历方式下的前驱与后继大多都不相同。

现在考虑这样一个问题,如果你想找到某一个树节点n的先序遍历前驱,你怎么做

通常的方法就是先遍历一遍,不断的保存前驱结点直到遍历到了n,于是保存下来的前驱就是n的前驱

但是吧,如果你不断的想要找各种节点的前驱,那么你每次就得遍历一遍树,这样是不是太没效率了


一个省时省力不省地方的办法就是你现在给树的节点加两个指针,一个指向它的前驱,一个指向它的后继。

这样,在遍历的过程中前驱后继的信息就能被记录好。但是一群喜欢较真的程序员们说你这样浪费地方。

一个有着k个结点的树,你就得多耗费2k个指针变量来保存这些信息。


就个人来说,我觉得这个放到现在来说真有点较劲,就现在的存储能力来说,处理具有1亿个节点的树,于是需要2亿个指针,每一个指针32位,就算64位机上指针64位,那么需要16亿BYTEs,不过1.5个g的内存。如果是32位机就是多花700M,而且通常我觉得也不会有人吃饱了撑得在内存里折腾1个亿的节点,这样规模的数据应该是在文件中一部分一部分的提取然后操作,于是,如果在这样规模的存储上,特别还得涉及到文件I/O的前提下,遍历来遍历去,耗费的时间是不是值得真是需要商榷。

以上是个人观点,欢迎拍砖。下面言归正传。


总而言之,你BOSS说咱们这穷,买不起内存,这时候怎么办?


这时候就用上你的子树指针,如果某一个节点n没有左子树,那么n的左子树指针就指向它的前驱,同样如果n没有右子树,那么n的右子树指针就指向它的后继。这样的树就叫做线索二叉树。

这样,叶子节点总是可以很方便的找到自己的前驱和后继,麻烦的就是子树的根。


对于先序线索树,节点n的后继就是左子树中最左下的那个子树的根。

对于中序线索树,节点n的后继就是右子树中最左下的节点。前驱是它的左子树下的最右边的节点。

对于后序线索树,这事就显得有点麻烦了。

如果n是整个树的根,那么n就没有后继。

如果n的双亲没有右子树或者n就是双亲的右孩子,那么n的后继就是n的双亲。

如果n的双亲有右子树,那么n就是右子树后序遍历的第一个节点。


最后,我们来讨论一下传说中的空间节省问题。

为了能实现线索二叉树,至少需要1个字节的数据来表示所有子树指针是否指向前驱后继或者是真正的子树,例如通过掩码来实现。0x00代表两根子树指针都指向前驱后继,0x01代表左指针是前驱。右指针是子树,0x02代表右指针是后继,左指针是子树,0x03代表两个子树指针都是子树等。

那么,它比多加两个指针节省了31个字节/节点 (63个字节/节点-64bit),空间节省还是很明显的。

但是吧,还是那句话,省地方就不省时间,省时间通常都不会省地方。怎么合适,自己看着来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值