[2010-8-18]

  1. 今日做PKU的一道最大流的题目,没有学过最大流的标准算法,靠自己的想法,不知道能不能过。不过我不想用递归实现,但发现非尾递归的解递归好难。当找到递归出口还,回溯过程比较繁琐。不过可以肯定,如果要解非尾递归,则必须在栈中保存之前的入栈项。

  2. 晕,原来我的红黑树一直是线性树,一直都没有发现,因为在非递归的中序遍历中,发现总是入栈N-1个节点才开始回溯,我才从调试中发现这个问题!!原因在于第一次调用递归插入函数的isSwitch参数总为false,这本来是没问题的,按照书上的写法,但原来我看漏了在每次插入后还要把整棵树的根节点设置为黑色,这样才能保证不会每次插入新节点,而恰好当这个节点每次都大于(或小于,主要看isSwitch为false时旋转的代码在哪边)根节点时,都旋转到同一边去,从而导致线性树!

  3. 找到我的非递归中序遍历算法的一个BUG了,我循环把每个节点的左节点入栈,每当遇到没有左节点的节点时,就认为要回溯,然后其父节点也会失去左节点,从而达到逐步回溯的效果,但我忽略了一点,就是父节点依然拥有左节点(尽管我把该左节点销毁了),一个解决方法是在每次父节点把左节点入栈后就马上删除链接,就可以达到我要的效果,但情况是我现在的功能不在乎这种破坏性的中序遍历,如果我需要遍历后树的结构依然不变,那怎么办?
   最后找到一个解决算法了,采用双循环,一个循环负责不断把节点压入栈,直到遇到有节点的左节点是空节点,就跳出该循环,进入回溯循环。因为左节点为空节点,意味着到达了当前可搜索范围的最小值。第二个循环负责回溯,直到回溯到需要压入新的节点。而这个时机就是,出栈的节点A,其右节点B不为空节点,而且不是A在栈中的下一个节点(因为这样的节点在压入A时已经被压入栈中,并且处于A的下一个位置,注意中序遍历压入栈的顺序是:右-中-左)。当遇到这样的节点,就代表遇到新的应该要入栈的节点,于是转回到入栈循环。不过这里有个要注意的地方,那就是在树中最右边缘的所有节点都一定会有这么一个情况:在回溯循环中处于栈元素的最后一个(即是不存在下一个元素),但同时又具有右节点,这怎么办?唯有单独出来判断,遇到这样的节点,其栈指针为0(栈中第一个),那就跳回入栈循环。
   没想到要维持结构来非递归进行中序遍历这么复杂,我总觉得有更简单的算法。我上述的算法要预先预计一下需要多大的栈,我是采用完美树高度 × 3的,入栈数最多就是树的左边缘所有节点 × 2 - 1, 一旦树变成线性树马上会爆栈,当然这对红黑树来说是不可能的。

  4. 树的内存释放我是采用DFS来销毁树中的节点,这里要注意判断根节点是否为空节点,否则就会销毁了空节点,而空节点本身又指向自己,肯定会出异常。

  5. 红黑树的插入真快,调试模式下插入2万个节点只需780毫秒,但变成线性树就要10多秒!

你可能感兴趣的:([2010-8-18])