Prolog中的表处理谓词

 
表元素枚举:member(X,L)
其中L为表,X为L中的元素。
表元素的枚举可以采用如下递归子句:
1、首先列举表的第一个元素
 member(X, [X|_]).
2、去掉表的第一个元素,对表尾进行递归处理
 member(X, [_|L]):-member(X, L).
~~~~~~~~~~~~~~~~~~
表元素判断:is_member(X,L)
在已知X的情况下,判断一个元素X是否属于表L的子句与表元素枚举谓词略有不同,其中,当第一个元素与X相同时,可以采用cut谓词阻止进一步的搜索。
 is_member(X, [X|_]):-!.
 is_member(X, [_|L]):-member(X, L).
~~~~~~~~~~~~~~~~~~
表的合并:append(L1, L2, L)
两个表的合成是指将两个表L1, L2的元素并在一起构成一个新表L。例如,表L1=[1,2,3]与表L2=[3,1,2,4]可以合并成一个新表L=[1,2,3,3,1,2,4],其中新表中前3个元素为第一个表的元素,后4个元素为第二个表的元素。
表的合并可以递归定义如下:
 append([], L, L).
 append([X|L1], L2, [X|L]):-append(L1, L2, L).
第一个子句描述了一个空表与一张表的合并结果就是该表本身;第二个子句描述了当合并两张表时,可以先将第一张表的首元素放入结果表中,然后,将第一张表的表尾与第二张表合并在一起,构成结果表的表尾。
在已知结果表的情况下,表的合并谓词还可以枚举各种情况下子表L1和L2的结果,对于目标:
goal
append(L1, L2, [1,2,3]).
生成的结果如下:
L1=[]; L2=[1,2,3]
L1=[1]; L2=[2,3]
L1=[1,2]; L2=[3]
L1=[1,2,3]; L2=[]
~~~~~~~~~~~~~~~~~~~~~~~
append谓词在Prolog程序设计中应用非常广泛,下面是几个简单的例子。
前缀表:prefix(P, L)
P为表L的前缀表,例如,表[1,2,3]的前缀表为[], [1], [1,2]及[1,2,3]
前缀表可以递归定义为:
 prefix([], _).
 prefix([H|P], [H|L]):-prefix(P, L).
也可以利用append谓词定义如下:
 prefix(P, L):-append(P, _, L).
~~~~~~~~~~~~~~~~~~~~
后缀表:suffix
同样地,后缀表可以定义为:
 suffix(L, L).
 suffix(S, [_|L]):-suffix(S, L).
也可以利用append谓词定义如下:
 suffix(S, L):-append(_, S, L).
~~~~~~~~~~~~~~~~~~
子表枚举sublist(Sub, L):枚举表L的子表Sub。
下面是子表谓词的各种定义方法及枚举的结果
算法1
 sublist(Sub, L):-
    append(L1, _, L),
    append(_, Sub, L1).
[]
[1]
[]
[1,2]
[2]
[]
[1,2,3]
[2,3]
[3]
[]
直接通过append谓词实现子表枚举。
缺点是产生大量空表。
算法2
 sublist([], _).
 sublist([H|Sub], L):-
    append(L1, _, L),
    append(_, [H|Sub], L1).
[]
[1]
[1,2]
[2]
[1,2,3]
[2,3]
[3]
对算法1的改进,保证不产生多余的空表。
算法3
 sublist(Sub, L):-
    append(L1, L2, L),
    append(Sub, _, L2).
[]
[1]
[1,2]
[1,2,3]
[]
[2]
[2,3]
[]
[3]
[]
 
算法4
 sublist([], _).
 sublist([H|Sub], L):-
    append(L1, L2, L),
    append([H|Sub], _, L2).
[]
[1]
[1,2]
[1,2,3]
[2]
[2,3]
[3]
对算法3的改进,保证不产生多余的空表。
算法5
 sublist(Sub, L):-
    prefix(P, L),
    suffix(Sub, P).
[]
[1]
[]
[1,2]
[2]
[]
[1,2,3]
[2,3]
[3]
[]
通过前缀表和后缀表来生成字表。
缺点是产生大量空表。
算法6
 sublist([], _).
 sublist([H|Sub], L):-
    prefix(P, L),
    suffix([H|Sub], P).
[]
[1]
[1,2]
[2]
[1,2,3]
[2,3]
[3]
对算法5的改进,只产生一次空表作为子表。
算法7
 sublist(Sub, L):-
    suffix(S, L),
    prefix(Sub, S).
[]
[1]
[1,2]
[1,2,3]
[]
[2]
[2,3]
[]
[3]
[]
 
算法8
 sublist([], _).
 sublist([H|Sub], L):-
    suffix(S, L),
    prefix([H|Sub], S).
[]
[1]
[1,2]
[1,2,3]
[2]
[2,3]
[3]
对算法7的改进,只产生一次空表作为子表。
算法9
 sublist(Sub, L):-prefix(Sub, L).
 sublist(Sub, [_|L]):-sublist(Sub, L).
[]
[1]
[1,2]
[1,2,3]
[]
[2]
[2,3]
[]
[3]
[]
 
算法10
 sublist([H|Sub], [H|L]):-prefix(Sub, L).
 sublist(Sub, [_|L]):-sublist(Sub, L).
 sublist([], []).
[1]
[1,2]
[1,2,3]
[2]
[2,3]
[3]
[]
 
我们选择算法8,其产生的结果比较符合习惯的次序。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
反序表reverse(L,R):对表L中所有元素进行反序,反序结果形成一张新表R。例如,表[1,2,3]反序后变成表[3,2,1]。
一个简单的递归算法为:对于表[H|L],首先求尾表L的反序表R1,然后将R1与[H]合并在一起,就构成了整个表[H|L]的反序表。
 reverse([], []).
 reverse([H|L], R):-
    reverse(L, R1),
    append(R1, [H], R).
也可以通过保存中间结果将反序操作过程改进为尾递归的形式:
 reverse(L, R):-reverse_3(L, [], R).
 
 reverse_3([H|L], T, R):-
    reverse_3(L, [H|T], R).
 reverse_3([], R, R).
其中,谓词reverse_3(L, T, R)中L为待反序的表,R为最后的反序表,而T保存前面已经反序的元素。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
表的长度:length(Length, L)—求表L的长度Length,对于空表,Length=0,对于n个元素构成的表,Length=n
表元素的个数称为表的长度。表长度谓词可以递归定义如下:递归求不计表头元素的尾表长度,而原表长度为尾表长度加1。
 length(0, []).
 length(Length, [_|L]):-
    length(Length0, L),
    Length = Length0 + 1.
上述子句比较低效,可以引入一个3元谓词length_3将递归改进为伪递归的形式:    
 length(Length, L):-length_3(Length, 0, L).
 
 length_3(Length, Length, []).
 length_3(Length, Length0, [_|L]):-
    Length1 = Length0 + 1,
    length_3(Length, Length1, L).
~~~~~~~~~~~~~~~~~~~~~~~~~
同理,表元素求和sum谓词也可以定义为:
 sum(Sum, L):-sum_3(Sum, 0, L).
 
 sum_3(Sum, Sum, []).
 sum_3(Sum, Sum0, [H|L]):-
    Sum1 = Sum0 + H,
    sum_3(Sum, Sum1, L).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
表元素的选择谓词pick(X,L,R):X为从L中选出的元素,而R为选出X后L中剩余元素组成的表。
 pick(X, [X|L], L).
 pick(X, [H|L1], [H|L2]):-pick(X, L1, L2).
~~~~~~~~~~~~~~~~~~~~~~~~
 表元素的删除delete(X,L,R):X为从L中删去的元素,而R为删去X后L中剩余元素组成的表。与pick谓词不同的是,执行这一谓词,需已知X,L,且一旦成功从L中删去元素X,就通过cut截断进一步的删去动作。
  delete(X, [X|L], L):-!.
 delete(X, [Y|L1], [Y|L2]):-delete(X, L1, L2).
~~~~~~~~~~~~~~~~~~~~~~~
 表中最大元素max_element(Max, L):从L中得到表中最大的元素值Max。
max_element(Max, [X|L]):-max_element_3(Max, X, L).
 
 max_element_3(Max, Max, []):-!.
 max_element_3(Max, Max0, [X|L]):-
    X > Max0, !,
    max_element_3(Max, X, L).
 max_element_3(Max, Max0, [_|L]):-
    max_element_3(Max, Max0, L).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 表中最小元素min_element(Min, L):从L中得到表中最大的元素值Min。
 min_element(Min, [X|L]):-min_element_3(Min, X, L).
 
 min_element_3(Min, Min, []):-!.
 min_element_3(Min, Min0, [X|L]):-
    X < Min0, !,
    min_element_3(Min, X, L).
 min_element_3(Min, Min0, [_|L]):-
    min_element_3(Min, Min0, L).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
表的第K个元素nth_element(X, K, L):从表L中取其第K个元素X。
 nth_element(X, 1, [X|_]):-!.
 nth_element(X, N, [_|L]):-
    N > 1,
    N1 = N - 1,
    nth_element(X, N1, L).
~~~~~~~~~~~~~~~~~~~~~~~~
表头元素first_element(X, L):取表L的首元素X。
 first_element(X, [X|_]).
表尾元素last_element(X, L):取表L的最后一个元素X。
 last_element(X, L):-append(_, [X], L).
~~~~~~~~~~~~~~~~~~~~~~~~
取表的第N个元素pick_nth_element(X, N, L, R):从表L中取走其第N个元素X,剩余元素放到表R中。
 pick_nth_element(X, N, [Y|L1], [Y|L2]):-
    N > 1, !,
    N1 = N - 1,
    pick_nth_element(X, N1, L1, L2).
 pick_nth_element(X, 1, [X|L], L).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值