简体   繁体   English

插入到位LISP

[英]Insertion sort in place LISP

I'm still pretty new to proper Lisp and I'm trying to build a simple, yet at least a bit efficient insertion sort - I would like to switch elements in place, but still have an ability to append to my container afterwards. 我对使用Lisp还是很陌生,我正在尝试构建一个简单但至少有效的插入排序-我想将元素切换到适当的位置,但之后仍然可以追加到我的容器中。 I took my old C++ implementation: 我采用了旧的C ++实现:

template<typename Iter>
void insertionSort(Iter begin, Iter end){
    for (auto i = begin; i != end; ++i){
        for (auto j = i; j != begin && *(std::prev(j)) > *(j); j--){
            std::iter_swap(j, std::prev(j));
        }
    }
}

And created the following code (taking into account that aref and rotatef have fair complexity), but it does not seem to take any effect on the input (UPD: now it simply works improperly), what might be wrong with my solution? 并创建了下面的代码(考虑到该帐户arefrotatef有公平的复杂性),但它似乎并没有采取对输入任何影响(UPD:现在它根本不能正常工作,),可能是什么毛病我的解决方案? I'm returning for testing purposes, should I create a macro in order to avoid pass-by-value? 我出于测试目的返回,是否应该创建宏以避免传递值?

(defparameter testa (make-array 4 :initial-contents '(2 3 1 5)))
(defun insertion-sort (vect)
    (loop for i from 0 to (1- (length vect)) do
        (loop for j from i downto 0
            until (or (= (1- j) -1) (> (aref vect (1- j)) (aref vect j)))
            do (rotatef (aref vect i) (aref vect (1- j))))
    )
    vect
)
(format t "~a~%" (insertion-sort testa))

UPD: updated the code based on the comments from @jkiiski and @RainerJoswig, the output is still wrong. UPD:根据@jkiiski和@RainerJoswig的注释更新了代码,输出仍然错误。

In your program there are several problems. 在您的程序中有几个问题。

First, the sort does not work since the line: 首先,由于该行,排序不起作用:

do (rotatef (aref vect i) (aref vect (1- j))))

should be: 应该:

do (rotatef (aref vect j) (aref vect (1- j))))

that is, you have written the variable i instead of j 也就是说,您编写了变量i而不是j

If you make this correction, you will find that the order is decreasing (I assume that you want an increasing order). 如果进行此更正,您会发现顺序在减少(我假设您要增加顺序)。 This depends on the use of until instead of while . 这取决于使用until而不是while

Finally, there is redundant code. 最后,有冗余代码。 A more simple and efficient version is the following: 下面是一个更简单有效的版本:

(defparameter testa (make-array 4 :initial-contents '(2 3 1 5)))
(defun insertion-sort (vect)
   (loop for i from 1 below (length vect) 
     do (loop for j from i above 0
          while (> (aref vect (1- j)) (aref vect j))
          do (rotatef (aref vect j) (aref vect (1- j)))))
   vect)
(format t "~a~%" (insertion-sort testa))

This parallel the pseudo-code in the wikipedia page of Insertion sort . 这与Insertion sort的Wikipedia页面中的伪代码并行。

If you want to parameterize the sorting predicate, as well as add an optional keyword-based “key” parameter to the function, here is a possible solution: 如果要对排序谓词进行参数化,以及向函数添加可选的基于关键字的“ key”参数,则可以采用以下解决方案:

(defun insertion-sort (vect predicate &key (key #'identity))
  (loop for i from 1 below (length vect) 
        do (loop for j from i above 0
                 while (funcall predicate 
                                (funcall key (aref vect (1- j)))
                                (funcall key (aref vect j)))
                 do (rotatef (aref vect j) (aref vect (1- j)))))
         vect)

CL-USER> (insertion-sort testa #'>)
#(1 2 3 5)
CL-USER> (insertion-sort testa #'<)
#(5 3 2 1)

CL-USER> (defparameter testa (make-array 4 :initial-contents '((c 3) (d 2) (b 1) (a 4))))
TESTA
CL-USER> (insertion-sort testa #'string> :key #'car)
#((A 4) (B 1) (C 3) (D 2))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM