我无法找到cdr
的时间复杂度分析。它是在恒定时间还是线性时间运行?如果答案取决于lisp的实现,假设我使用的是Racket。
答案 0 :(得分:8)
cdr
可以在任何Lisp中占用恒定的时间。它只是查找cons
单元格中的第二个成员。
答案 1 :(得分:7)
根据C来思考,lisp对只是struct
,包含两个字段car
和cdr
。 lisp函数car
和cdr
仅用于访问每个字段。
以下是对part of Racket's scheme.h
的了解:
typedef struct Scheme_Simple_Object
{
Scheme_Inclhash_Object iso;
union
{
struct { mzchar *string_val; intptr_t tag_val; } char_str_val;
struct { char *string_val; intptr_t tag_val; } byte_str_val;
struct { void *ptr1, *ptr2; } two_ptr_val;
struct { int int1; int int2; } two_int_val;
struct { void *ptr; int pint; } ptr_int_val;
struct { void *ptr; intptr_t pint; } ptr_long_val;
struct { struct Scheme_Object *car, *cdr; } pair_val;
struct { mzshort len; mzshort *vec; } svector_val;
struct { void *val; Scheme_Object *type; } cptr_val;
} u;
} Scheme_Simple_Object;
请注意union
:
struct { struct Scheme_Object *car, *cdr; } pair_val;
#define SCHEME_CAR(obj) (((Scheme_Simple_Object *)(obj))->u.pair_val.car)
#define SCHEME_CDR(obj) (((Scheme_Simple_Object *)(obj))->u.pair_val.cdr)
当然,Racket cdr
函数将比这个C宏做更多的工作,例如检查它是否被赋予pair?
。
答案 2 :(得分:1)
球拍definition of a pair将car
和cdr
对话作为配对存取,因此间接将其指定为O(1)。要使cdr
成为O(n),你必须将其反转为butlast
并且不符合球拍文档。
球拍母语,Scheme,有一个R6RS spec,其中car
和cdr
是pair
中的字段的访问者,也是间接的O(1)。
在Common Lisp中,Scheme的菜肴有类似的描述,唯一的区别是他们在规范中使用名称cons
而不是pair
。 (你标记了lisp)
虽然这并不是特意,因为cons
/ pairs
是由所有LISP的母亲John McCarthy's LISP定义的基本数据类型,并且它的第一个实现具有检索某些东西的汇编指令名为address and decrement from a memory location,car
/ cdr
中的字母a和d来自该术语。