SWI Prolog插入谓词解决方案分步解析求助(初学者)
分步解析Prolog insert谓词的运行机制
我们先明确两个子句的核心逻辑,再通过你的示例查询一步步拆解完整运行过程:
两个子句的作用
基础子句:
insert(I, L, [I|L])
直接把元素I插在列表L的最开头,生成新列表[I|L],这是你已经理解的第一个解。递归子句:
insert(I, [H|L], [H|L2]) :- insert(I, L, L2)
逻辑是:如果能把I插入到列表[H|L]的尾部L中得到L2,那么把H放在L2的最前面,就是I插入到原列表的一个新位置。简单说就是——先保留列表的第一个元素H,再递归处理剩下的部分,把I插到剩余列表的任意位置。
示例查询的完整运行过程
以insert(Item, [Zero, One, Two], L)为例,一步步看Prolog如何生成所有解:
第一步:生成第一个解(基础子句匹配)
Prolog首先尝试匹配基础子句:
I=Item,L=[Zero, One, Two]- 直接生成结果
L = [Item, Zero, One, Two] - 按
;触发回溯,Prolog开始寻找下一个解。
第二步:生成第二个解(第一次递归)
回溯后,Prolog尝试匹配递归子句:
- 把原列表
[Zero, One, Two]拆分为H = Zero和尾部L = [One, Two] - 递归调用子目标:
insert(Item, [One, Two], L2) - 该子目标先匹配基础子句,得到
L2 = [Item, One, Two] - 原结果
L为[H|L2]→[Zero, Item, One, Two]
- 这是第二个输出结果,再按
;继续回溯。
第三步:生成第三个解(第二次递归)
回溯到子目标insert(Item, [One, Two], L2),尝试它的递归子句:
- 把
[One, Two]拆分为H = One和尾部L = [Two] - 递归调用子目标:
insert(Item, [Two], L3) - 该子目标匹配基础子句,得到
L3 = [Item, Two] - 上层的
L2=[One|L3]→[One, Item, Two] - 原结果
L=[Zero|L2]→[Zero, One, Item, Two]
- 这是第三个输出结果,按
;继续回溯。
第四步:生成第四个解(第三次递归)
回溯到子目标insert(Item, [Two], L3),尝试它的递归子句:
- 把
[Two]拆分为H = Two和尾部L = [] - 递归调用子目标:
insert(Item, [], L4) - 该子目标只能匹配基础子句(空列表无法拆分),得到
L4 = [Item] - 上层的
L3=[Two|L4]→[Two, Item] - 再上层的
L2=[One|L3]→[One, Two, Item] - 原结果
L=[Zero|L2]→[Zero, One, Two, Item]
- 这是第四个输出结果,按
;继续回溯。
第五步:无更多解,返回false
回溯到子目标insert(Item, [], L4),它没有递归子句可匹配(空列表无法拆分为[H|L]),Prolog向上回溯所有层级后,没有其他子句可以尝试,最终返回false。
内容的提问来源于stack exchange,提问作者anon8107
相关产品推荐
相关产品推荐

