我认为这已经完成了图灵:我们可以使用此技巧来编写一个模拟UTM的程序(我很快就手工编写了代码,因此可能存在一些语法错误...但是我希望逻辑中没有(主要)错误。 :-)
typdef struct {
cell_t * pred; //左侧的单元格
cell_t * succ; //右边的单元格
int val; //储存格值
} cell_t
的head
将是一个指向cell_t
结构
typedef struct {
int状态
int标志;
} info_t
- 然后定义一个单循环函数,当头部位于双链表的边界之间时,该函数将模拟Universal TM;当头部碰到边界时,设置info_t结构的标志(HIT_LEFT,HIT_RIGHT)并返回:
void Simulation_UTM(cell_t * head,info_t * info){
而(true){
head-> val = UTM_nextsymbol [info-> state,head-> val]; //写符号
info-> state = UTM_nextstate [info-> state,head-> val]; //下一个状态
if(info-> state == HALT_STATE){//打印是否接受并退出程序
putchar((info-> state == ACCEPT_STATE)?'1':'0');
退出(0);
}
int move = UTM_nextmove [info-> state,head-> val];
如果(移动== MOVE_LEFT){
head = head-> pred; // 向左移动
如果(head == NULL){info-> flag = HIT_LEFT; 返回; }
}其他{
头=头->成功; // 向右移
如果(head == NULL){info-> flag = HIT_RIGHT; 返回; }
}
} //仍在边界中……继续
}
- 然后定义一个递归函数,该函数首先调用模拟UTM例程,然后在需要扩展磁带时递归调用自身。当磁带需要在顶部扩展(HIT_RIGHT)没问题时,当磁带需要在底部扩展(HIT_LEFT)时,只需使用双链表向上移动单元格的值即可:
void stacker(cell_t * top,cell_t * bottom,cell_t * head,info_t * info){
Simulation_UTM(head,info);
cell_t newcell; //新单元格
newcell.pred =顶部; //用新单元格更新双链表
newcell.succ = NULL;
top-> succ =&newcell;
newcell.val = EMPTY_SYMBOL;
开关(信息->点击){
案例HIT_RIGHT:
堆栈器(&newcell,bottom,newcell,info);
打破;
案例HIT_BOTTOM:
cell_t * tmp = newcell;
while(tmp-> pred!= NULL){//上移值
tmp-> val = tmp-> pred-> val;
tmp = tmp-> pred;
}
tmp-> val = EMPTY_SYMBOL;
堆栈器(&newcell,bottom,bottom,info);
打破;
}
}
- 初始磁带可以用一个简单的递归函数填充,该函数构建双链表,然后
stacker
在读取输入磁带的最后一个符号时调用该函数(使用readchar)
void init_tape(cell_t * top,cell_t * bottom,info_t * info){
cell_t newcell;
int c = readchar();
如果(c == END_OF_INPUT)堆栈器(&top,bottom,bottom,info); //没有更多的符号,开始
newcell.pred =顶部;
如果(top!= NULL)top.succ =&newcell; else bottom =&newcell;
init_tape(&newcell,bottom,info);
}
编辑:经过一番思考之后,指针出现了问题...
如果递归函数的每个调用都stacker
可以维护一个有效的指针指向调用者本地定义的变量,那么一切都很好 ; 否则,我的算法将无法在无限递归上保留有效的双向链接列表(在这种情况下,看不到使用递归模拟无限随机访问存储的方法)。