Vector 求向量的第二小值

Vector 求向量的第二小值,vector,scheme,racket,minimum,Vector,Scheme,Racket,Minimum,我已经解释了一个过程,它应该以一个参数,一个以数字为条目的向量,然后返回最小值 (define min-number (lambda (vec) (define looping (lambda (i v-min) (if (= i (vector-length vec)) v-min (looping (+ i 1) (min v-min (vector-ref vec i)))))) (loopin

我已经解释了一个过程,它应该以一个参数,一个以数字为条目的向量,然后返回最小值

(define min-number
  (lambda (vec)
    (define looping
      (lambda (i v-min)
        (if (= i (vector-length vec))
            v-min
            (looping (+ i 1) (min v-min (vector-ref vec i))))))
    (looping 1 (vector-ref vec 0))

    )
  )
现在我想构造一个过程,返回向量的第二小值。这是在不将向量转换为列表的情况下应该执行的操作。你知道我该怎么做吗?我不能让我的头从名单上离开思考。我的大脑告诉我使用汽车,使用cdr等等,在这种特殊情况下不起作用。因此,任何想法都将不胜感激。嗯,我想我涵盖了一切,如果有不清楚的地方,请告诉我


谢谢:

如果允许使用内置函数,这里有一个简单的方法:找到最小值,然后查找下一个不是最小值的最小值。这就是我的意思:

(define min-number
  (lambda (vec)
    (let ((min-val (vector-argmin identity vec)))
      (vector-argmin
       (lambda (x) (if (equal? x min-val) +inf.0 x))
       vec))))
例如:

(min-number '#(5 4 1 2 3))
=> 2

快速选择算法很好地解决了寻找向量第k个最小元素的问题

(define (quickselect A k)
  (define pivot (list-ref A (random (length A))))
  (define A1 (filter (curry > pivot) A))
  (define A2 (filter (curry < pivot) A))
  (cond
    [(<= k (length A1)) (quickselect A1 k)]
    [(> k (- (length A) (length A2))) (quickselect A2 (- k (- (length A) (length A2))))]
    [else pivot]))

(quickselect '(9 8 7 6 5 0 1 2 3 4) 2)  ; => 1

代码来自另一种方法,类似于Óscar的答案,两者都是开启的。这一个适用于任何序列,包括列表和向量

(define (second-lowest seq)
  (define-values (_ x)
    (for/fold ((a #f) (b #f))
              ((x seq))
      (cond ((< x (or a (add1 x))) (values x a))
            ((< x (or b (add1 x))) (values a x))
            (else (values a b)))))
  x)
下面是vector select的两个版本,它查找向量v中的第k个最小元素。这意味着vector select v 1将查找向量中第二个最小的元素。向量选择和向量选择之间的区别!后者可能会改变向量中元素的顺序。这两个过程的预期时间均为On,其中n是向量的长度

#lang racket
; vector-ref and vector-set! is used so often, so introduce shorter notation
(define-syntax-rule (vref  v i)   (vector-ref  v i))
(define-syntax-rule (vset! v i e) (vector-set! v i e))

; vector-select : vector index -> number
;   find the kth largest element of v
;   (where 0 <= k < n )
(define (vector-select v k) 
  (define n (vector-length v))
  (unless (<= 0 k (- n 1))
    (error 'vector-select "expected a number between 0 and the length of the vector"))
  (subvector-select! (vector-copy v) k 0 n))

; vector-select! : vector index -> number
;   find the kth largest element of v
;   (where 0 <= k < n )
;   side effect: the order of the elements may change
(define (vector-select! v k) 
  (define n (vector-length v))
  (unless (<= 0 k (- n 1))
    (error 'vector-select! "expected a number between 0 and the length of the vector"))
  (subvector-select! v k 0 n))

; subvector-select : vector index index index -> number
;   find the kth largest element of the elements v[s],v[s+1],...,v[t-1].
;   assumption: s<t  (i.e. the subvector is non-empty)
(define (subvector-select! v k s t)
  (define n (- t s)) ; length of subvector
  (cond
    [(= n 1) (unless (= k 0) (error "Error 1"))
             (vref v s)]
    [else    (define r (randomized-partion! v s t)) ; v[r] is a pivot
             (define l (- r s))                     ; number of elements left of pivot (in subvector)
             (cond
               [(= k l) (vref v r)]                             ; found it!
               [(< k l) (subvector-select! v    k     s r)]     ; the element is left  of the pivot
               [else    (subvector-select! v (- k l)  r t)])])) ; the element is right of the pivot

; randomized-partion! : vector index index -> index
;   Pick a random index between s and t, then partion the elements
;   in the subvector v[s],v[s+1],...,v[t-1] using v[r] as pivot.
;   I.e. move elements smaller than the pivot to appear before the pivot
;   and  move elements larger  than the pivot to appear after  the pivot.
;   Finally return the index of the pivot.
(define (randomized-partion! v s t)
  ;; Helper
  ; swap! : index index -> void
  ;   swap elements with index i and j
  (define (swap! i j) 
    (define vi (vref v i))          
    (vset! v i (vref v j))          
    (vset! v j vi))
  ;; Main
  (define r (+ s (random (- t s)))) ; pick random pivot index in subvector
  (define p (vref v r))             ; the pivot value
  (swap! (- t 1) r)                 ; place the pivot as the last value in the subvector
  (define i s)                      ; invariant: all elements before v[i] are <= pivot
  (for ([j (in-range s (- t 1))])   ;   loop through all elements (except the pivot)
    (when (<= (vref v j) p)         ;     if the element is non-greater than the pivot
      (swap! i j)                   ;       move it to the front of the subvector
      (set! i (+ i 1))))            ;       and update i to the next available slot
  (swap! i (- t 1))
  i)                                ;   finally put the pivot in place

谢谢,我想这样就行了:为什么这么多人在做手术我想这是你的罗塞塔代码。@ChrisJester Young你是对的-这个版本不是一个有效代码的例子。我从头开始写了一个向量select。看看新的答案。