我的上一篇blog是关于AttachInst函数的代码解析,它的最后调用了ReOrderList,来重新排序待进入下一个识别的节点。下面接着看它是如何处理识别过程的。
传入的参数依然是pri->net->initial,它包含两个for循环,且第二个for循环调用自身,也就是说它是个递归函数。
一个一个来分析,力图彻底掌握,在头脑中构建清晰的画面。
循环的结束条件是遍历了所有initial指向的开始节点,都是先跳过tr0的节点,这是因为它可以实现从start状态点直接转移到final状态点,从而越过这个hmm模型,不占用时间。且,我们在之前分析时说过,每个节点的指向下一个/多个的连接是经过排序的,指向tr0类型的连接被放在开头。
static void ReOrderList(NetNode *node)
{
NetLink *dest;
int i;
if (node->inst!=NULL?!node->inst->ooo:TRUE) return;
node->inst->ooo=FALSE;
for (i=0,dest=node->links;i<node->nlinks;i++,dest++) {
if (!node_tr0(dest->node)) break;
if (dest->node->inst!=NULL)
MoveToRecent(dest->node->inst);
}
for (i=0,dest=node->links;i<node->nlinks;i++,dest++) {
if (!node_tr0(dest->node)) break;
if (dest->node->inst!=NULL)
ReOrderList(dest->node);
}
}
现在看函数MoveToRecent的内容了。
static void MoveToRecent(NetInst *inst)
{
if (inst->node==NULL) return;
/* If we are about to move the instance that is used to determine the */
/* next instance to be stepped (to the most recent end of the list) we */
/* must use the previous instance to determine the next one to step !! */
if (inst==pri->nxtInst)
pri->nxtInst=inst->knil;
inst->link->knil=inst->knil; /* 将inst从原列表中剔除*/
inst->knil->link=inst->link;
inst->link=&pri->tail;
inst->knil=pri->tail.knil;
inst->link->knil=inst;
inst->knil->link=inst; /* 将inst插入pri->tail之前*/
inst->pxd=FALSE;
inst->ooo=TRUE;
#ifdef SANITY
if (inst==pri->start_inst)
HError(8521,"MoveToRecent: Loop resulted in circular move");
inst->ipos=pri->ipos++;
#endif
}
我新加入的注释解释了MoveToRecent函数的主要目的,就是将函数的参数,从它原来的列表中删除,并插入到pri->tail之前。循环执行,就是将当前节点的所有连接指向的节点携带的inst添加进入pri->trail中,接下来给每个节点的子节点再做同样的操作,可以看出是实现了深度优先算法遍历Network图网络。