Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 如何仅使用基本操作递归地反转列表?_List_Recursion_Scheme_Lisp - Fatal编程技术网

List 如何仅使用基本操作递归地反转列表?

List 如何仅使用基本操作递归地反转列表?,list,recursion,scheme,lisp,List,Recursion,Scheme,Lisp,我想知道如何仅使用cons、first、rest、empty等基本操作来反转列表 不允许使用辅助函数或累加器,该函数只接受一个输入-列表 有人告诉我这是可能的,尽管我不能完全相信 这就是我到目前为止的概念。我不知道如何为列表的其余部分形成递归 (defunc rev-list (x) (if (or (equal (len x) 0) (equal (len x) 1)) x (cons (first (rev-list (rest x)))

我想知道如何仅使用cons、first、rest、empty等基本操作来反转列表

不允许使用辅助函数或累加器,该函数只接受一个输入-列表

有人告诉我这是可能的,尽管我不能完全相信

这就是我到目前为止的概念。我不知道如何为列表的其余部分形成递归

(defunc rev-list (x)
  (if (or (equal (len x) 0) (equal (len x) 1))
      x
      (cons (first (rev-list (rest x)))
            ???)))
显然,可以使用交换列表的第一个和最后一个的函数来执行类似的操作,尽管我也不完全理解。下面是它的代码:

(define swap-ends (x)
  (if (or (equal (len x) 0) (equal (len x) 1))
      x
      (cons (first (swap-ends (rest x))) 
            (swap-ends (cons (first x) 
                             (rest (swap-ends (rest x))))))))

您的环境中是否有
last
butlast
?如果是这样的话,这个过程可以这样定义(尽管正如Oscar所指出的,这不是你通常想要解决问题的方式):

以下是
last
butlast
的定义。如果它们不是您默认环境的一部分,听起来它们对您的任务没有任何好处,但是当您刚开始时,最好通读并思考许多递归过程

(define (butlast lst)
  (if (or (null? lst) (null? (cdr lst)))
      '()
      (cons (car lst) (butlast (cdr lst)))))

(define (last lst)
  (if (or (null? lst) (null? (cdr lst)))
      lst
      (last (cdr lst))))
真的是为数不多的有效方法之一。但仍然是一种辅助程序

另一种方式,但不是尾部递归,如果追加不使用集合cdr!对于大型列表来说,它确实无法使用

(define (reverse L)
  (if (null? l)
      '()
       (append (reverse (cdr L)) (list (car L)))))
(注:答案在本文底部)第二个功能

(define (swap-ends x)                                   ; swap [] = []
  (if (or (equal (length x) 0) (equal (length x) 1))    ; swap [x] = [x]
      x                                                 ; swap (x:xs) 
      (cons (first (swap-ends (rest x)))                ;    | (a:b) <- swap xs 
            (swap-ends (cons (first x)                  ;    = a : swap (x : b)
                             (rest (swap-ends (rest x))))))))
(按照从左到右的箭头进行操作)。所以

到目前为止,它确实交换了列表的结束元素。让我们用自然归纳法来证明它

true(N-1)=>true(N)

事实证明了这一点。因此,我们需要设计一个数据流图,在反转(N-1)长度列表的假设下,它将反转N长度列表:

[1..N] --> 1 ------------------------------------\
       \-> [2..N] -> [N,N-1..2] -> N -------------\------------------\
                     \-> [N-1,N-2..2] -> [2..N-1] -> [1..N-1] -> rev -> cons
这给了我们实现的机会

(define (rev ls)                                 ; rev [] = []
  (cond                                          ; rev [x] = [x]
    ((null? ls) ls)                              ; rev (x:xs) 
    ((null? (rest ls)) ls)                       ;   | (a:b) <- rev xs 
    (else                                        ;   = a : rev (x : rev b)
      (cons (first (rev (rest ls)))
            (rev (cons (first ls)
                       (rev (rest (rev (rest ls))))))))))

(rev '(1 2 3 4 5))     ; testing
;Value 13: (5 4 3 2 1)

在这里,的概念可能对您有所帮助。我知道如何使用first(car)和rest(cdr),但我不知道如何为列表的递归构建适当的列表。我不知道,这使它变得更加困难。但是,有一种方法可以在不使用实际命令的情况下获取列表的最后一个,那就是调用(first(rev list(rest x)),假设基本情况与我在示例中遇到的情况相同。您对该过程有书面要求吗?这可能有助于我们逐字阅读它们。仅当、cons、first、rest、empty时使用?(endp)或len,编写一个接受列表(仅输入)并将其反转的函数。不允许使用任何辅助函数。我得到了使用这些限制的交换端解决方案,这在概念上是相似的。我确信,如果我了解它是如何工作的,我将能够为反向列表做类似的事情。在以前(现在已删除)的回答中,OP说他也不能使用
附加
。您的第一个变体使用助手,就像我自己的第二个变体一样。我认为严格遵守OP的所有限制是不可能的,很可能他误解了问题描述。这里试图使Scheme版本具有类似的可读性:。
                   /-> first ----------------------> cons
x --> first ------/-------------> cons --> swap --/
  \-> rest -> swap ---> rest ---/
[] -> []
[1] -> [1]
                     /-> 2 -----------------------> [2,1]
[1,2] --> 1 --------/------------> [1] --> [1] --/
      \-> [2] -> [2] ---> [] ---/

                           /-> 3 -------------------------> [3,2,1]
[1,2,3] --> 1 ------------/----------> [1,2] --> [2,1] --/
        \-> [2,3] -> [3,2] -> [2] --/

                             /-----> 4 ----------------------------> [4,2,3,1]
[1,2,3,4] --> 1 ------------/---------------> [1,3,2] -> [2,3,1] -/
          \-> [2,3,4] -> [4,3,2] -> [3,2] -/
                       /-> N --------------------------------------> [N,2..N-1,1]
[1..N] --> 1 ---------/-----------> [1,3..N-1,2] -> [2,3..N-1,1] -/
       \-> [2..N] -> [N,3..N-1,2]   /
                    -> [3..N-1,2] -/
[1..N] --> 1 ------------------------------------\
       \-> [2..N] -> [N,N-1..2] -> N -------------\------------------\
                     \-> [N-1,N-2..2] -> [2..N-1] -> [1..N-1] -> rev -> cons
(define (rev ls)                                 ; rev [] = []
  (cond                                          ; rev [x] = [x]
    ((null? ls) ls)                              ; rev (x:xs) 
    ((null? (rest ls)) ls)                       ;   | (a:b) <- rev xs 
    (else                                        ;   = a : rev (x : rev b)
      (cons (first (rev (rest ls)))
            (rev (cons (first ls)
                       (rev (rest (rev (rest ls))))))))))

(rev '(1 2 3 4 5))     ; testing
;Value 13: (5 4 3 2 1)
(define (bind lst fun)
  (apply fun lst))

(define (rev lst)
  (if (or (null? lst)
          (null? (cdr lst)))
    lst
    (bind lst
      (lambda (first . rest)
         (bind (rev rest)
           (lambda (last . revd-core)
              (cons last (rev (cons first (rev revd-core))))))))))