Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.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
Sorting lisp格式的排序算法_Sorting_Lisp_Scheme - Fatal编程技术网

Sorting lisp格式的排序算法

Sorting lisp格式的排序算法,sorting,lisp,scheme,Sorting,Lisp,Scheme,我已经决定学习一些函数式语言,毕竟我已经学会了lisp模式 我正在尝试创建一个函数,它检查列表是否已排序,最低优先级是否会越高,反之亦然,如果可以排序,则应返回true或false 这是我的第一个代码,仅当列表增加(或相等)时才起作用 (定义排序? (兰姆达(lst) (cond((空的?lst)#t) (或者(你几乎把它做好了,看: (define sorted? (lambda (lst) (cond ((or (empty? lst) (empty? (cdr lst)))

我已经决定学习一些函数式语言,毕竟我已经学会了lisp模式

我正在尝试创建一个函数,它检查列表是否已排序,最低优先级是否会越高,反之亦然,如果可以排序,则应返回true或false

这是我的第一个代码,仅当列表增加(或相等)时才起作用

(定义排序?
(兰姆达(lst)
(cond((空的?lst)#t)

(或者(你几乎把它做好了,看:

(define sorted?
  (lambda (lst)
    (cond ((or (empty? lst) (empty? (cdr lst)))
           #t)
          (else (and (<= (car lst) (cadr lst))
                     (sorted? (cdr lst)))))))
现在,如果您想知道列表是按升序排序还是按降序排序:

(define lst '(1 2 3 4 5))
(or (sorted? lst >=) (sorted? lst <=))
> #t
(定义lst'(1 2 3 4 5))
(或(已排序的?lst>=)(已排序的?lst#t

正如您所见,函数式编程是指尽可能将过程定义为通用的,并将它们结合起来解决问题。您可以将函数作为参数传递,这一事实对实现通用函数有很大帮助。

特定实现

我会更进一步:

(define sorted? (lambda (lst)
  (letrec ((sorted-cmp 
            (lambda (lst cmp)
              (cond ((or (empty? lst) (empty? (cdr lst)))
                     #t)
                    (else (and (cmp (car lst) (cadr lst))
                               (sorted-cmp (cdr lst) cmp)))))))
    (or (sorted-cmp lst <=) (sorted-cmp lst >=)))))
(定义已排序的?(lambda(lst)
(letrec((已排序的cmp)
(lambda(第一次cmp)
(条件((或(空?lst)(空?(cdr lst)))
#(t)
(其他(和(cmp(车辆lst)(cadr lst))
(已排序cmp(cdr lst)cmp()()())))
(或(已排序的cmp lst=()()))
此版本与his的最大区别在于
sorted?
现在使用
letrec
将Óscar的版本定义为一个内部帮助函数,并对其进行双向调用

功能性思维

实际上,您选择了一个很好的示例来说明Scheme如何看待世界的某些方面,并且您的实现有了一个很好的开端


解决这个问题所涉及的一个重要功能原则是,您可以将任何内容放入
(**此处**更多内容”(1 2 3 4))
,您可以将其作为参数传递给另一个函数。也就是说,函数是函数式编程语言中的第一类。因此,您使用的是
,我想更具体地说,您的问题的意思是,“如果我已经用命令式语言(如C或Java)编程,我如何调整函数式编程的思维?”?“以你的问题为例,我将用周六上午的时间详细回答这个问题。我将通过三个阶段跟踪函数式程序员的发展,每个阶段都是禅宗的一个连续的更高层次——1)迭代地思考;2)递归地思考;3)懒洋洋地思考

第一部分——反复思考 假设我用C语言编程,我不能也不会使用递归——也许编译器没有优化尾部递归,递归解决方案会溢出堆栈。所以我开始考虑我需要保持什么状态。我想象一台小机器在输入上爬行。它会记得它是在搜索递增还是递减asing sequence。如果它还没有决定,它会根据当前输入(如果可以的话)来决定。如果它发现输入指向错误的方向,它将以zigzag=true终止。如果它到达输入的末尾,它将以zigzag=false终止

int
zigzag(int *data, int n)
{
  enum {unknown, increasing, decreasing} direction = unknown;

  int i;
  for (i = 1; i < n; ++i)
    {
      if (data[i] > data[i - 1]) {
    if (direction == decreasing) return 1;
    direction = increasing;
      }
      if (data[i] < data[i - 1]) {
    if (direction == increasing) return 1;
    direction = decreasing;
      }
    }

  /* We've made it through the gauntlet, no zigzagging */
  return 0;
}
现在我们需要定义
最初增加
最初减少
减少
,和
增加
最初-
函数非常简单:

(define (initially-increasing xs)
  (> (cadr xs) (car xs)))

(define (initially-decreasing xs)
  (< (cadr xs) (car xs)))
我们可以编写一个类似的
增加
函数,但显然只需要一个更改:
。复制这么多代码会让你感到不安。难道我不能要求语言让我的函数像
减少
,而是在函数语言中使用
,您可以做到这一点,因为函数可以返回其他函数!因此我们可以编写一个函数来实现:“给定一个比较运算符,如果其参数的任意两个连续元素的比较为真,则返回一个返回真的函数。”

增加
减少
现在都可以非常简单地定义:

(define decreases (ever <))
(define increases (ever >))
现在我需要一种方法来推导
比较
,即
xs
的每个成员与其后继成员的比较列表。这并不难做到,也许最好通过示例来解释

> xs
[1,1,1,2,3,4,5,3,9,9]

> zip xs (tail xs)
[(1,1),(1,1),(1,2),(2,3),(3,4),(4,5),(5,3),(3,9),(9,9)]

> map (\(x,y) -> compare x y) $ zip xs (tail xs)
[EQ,EQ,LT,LT,LT,LT,GT,LT,EQ]
这就是我们所需要的;这两行是完整的实现-

zigzag xs = LT `elem` comparisons && GT `elem` comparisons
  where comparisons = map (\(x,y) -> compare x y) $ zip xs (tail xs)
我要注意的是,这个程序只通过一次列表来测试递增和递减情况

到目前为止,您可能已经想到了一个反对意见:这种方法不是很浪费吗?当它只需要搜索到第一次方向改变时,它不是要搜索整个输入列表吗?实际上,不,它不会,因为惰性评估。在上面的示例中,它计算整个比较列表是因为它必须打印出来,但是如果将结果传递给<代码>锯齿形< /代码>,它只会对比较列表进行足够的评估,以找到一个实例:<代码> GT以及<代码> Lt,并且不再进一步。要说服自己,请考虑以下情况:

> zigzag $ 2:[1..]
True
> zigzag 1:[9,8..]
True
这两种情况下的输入都是一个无限列表([2,1,2,3,4,5..]和[1,9,8,7,6,5…])。尝试将它们打印出来,它们将填满屏幕。但将它们传递到
之字形
,一旦找到第一个方向变化,它将很快返回

读取代码的许多困难来自于控制流的多个分支。这些分支中的许多实际上是为了避免计算超出我们需要的量。但是,通过延迟求值可以实现许多相同的事情,使程序比原始问题更短、更真实。

试试这个

(define sorted?
  (lambda (l)
     (cond ((null? l) #t)
           (else (check-asc? (car l) (sorted? (cdr l))
                 (check-desc? (car l) (sorted? (cdr l))))))


(define check-asc?
  (lambda (elt lst)
     (cond ((null? lst) #t)
           (else (or (< elt (car lst)) (= elt (car lst))) (check-asc? (car lst) (cdr lst))))))

(define check-desc?
  (lambda (elt lst)
     (cond ((null? lst) #t)
           (else (or (< elt (car lst)) (= elt (car lst))) (check-desc? (car lst) (cdr lst))))))
(定义排序?
(λ(l)
(条件((空?l)#t)
(其他(检查asc?(车辆l)(已分拣)(c
(define decreases (ever <))
(define increases (ever >))
zigzag xs = LT `elem` comparisons && GT `elem` comparisons
> xs
[1,1,1,2,3,4,5,3,9,9]

> zip xs (tail xs)
[(1,1),(1,1),(1,2),(2,3),(3,4),(4,5),(5,3),(3,9),(9,9)]

> map (\(x,y) -> compare x y) $ zip xs (tail xs)
[EQ,EQ,LT,LT,LT,LT,GT,LT,EQ]
zigzag xs = LT `elem` comparisons && GT `elem` comparisons
  where comparisons = map (\(x,y) -> compare x y) $ zip xs (tail xs)
> zigzag $ 2:[1..]
True
> zigzag 1:[9,8..]
True
(define sorted?
  (lambda (l)
     (cond ((null? l) #t)
           (else (check-asc? (car l) (sorted? (cdr l))
                 (check-desc? (car l) (sorted? (cdr l))))))


(define check-asc?
  (lambda (elt lst)
     (cond ((null? lst) #t)
           (else (or (< elt (car lst)) (= elt (car lst))) (check-asc? (car lst) (cdr lst))))))

(define check-desc?
  (lambda (elt lst)
     (cond ((null? lst) #t)
           (else (or (< elt (car lst)) (= elt (car lst))) (check-desc? (car lst) (cdr lst))))))
(define sorted?
 (lambda (l)
   (cond ((null? l) #t)
       (else (if (check-asc? (car l) (cdr l)) #t
             (check-desc? (car l) (cdr l)))))))


(define check-asc?
(lambda (elt lst)
  (cond ((null? lst) #t)
       (else (if (or (< elt (car lst)) (= elt (car lst))) (check-asc? (car lst) (cdr lst))
                 #f)))))

(define check-desc?
 (lambda (elt lst)
  (cond ((null? lst) #t)
       (else (if (or (> elt (car lst)) (= elt (car lst))) (check-desc? (car lst) (cdr lst))
                 #f)))))