简体   繁体   中英

Insertion sort in r with error “missing value where TRUE/FALSE needed”

I want to build insertion sort algorithm in r:

  1. Given a vector x, let the initial unsorted vector u be equal to x,
    and the initial sorted vector s be a vector of length 0.
  2. Remove first element of u and insert it into s so that s is still sorted.
  3. If u is not empty then go back to step 2.

Here is my code:

x <- round(runif(1000,1,100)
u <- x
s <- vector(mode="numeric", length=0


    for(i in 1:length(u)){
        number <-u[i]
        u <- u[-i]
        for(j in 1:length(s)){
            if(length(s) == 0){
                s <- c(s,number)
                break
            }else{
                if(s[j]>=number){
                    s <- append(s,number,j-1)
                    break
                }
            }
            if(s[length(s)]<number){
                s <- c(s,number)
            }
        }
    }

First of all, when length of u = 500 it throws me an error:

Error in if (s[j] >= number) { : missing value where TRUE/FALSE needed

next, it sorted incorrectly(for example it could be more ones than in original vector u, or for example less twos then in original vector u)

So I have two questions:

1)How can we fix that in THIS code?

2)Can you suggest another code, which is more efficient than my?

PS Of course the code should be without sort and order command. Many thanks

Your first question is an easy fix: when you extract a number out of your vector u, what you are really doing, is just drawing a random number from the sample without replacement. So just always take the first value.

# Change the current to this:
number <-u[1]
u <- u[-1]

For your second question: what a fun exercise! My go at it was to just implement the selection sort pseudo-code from Wikipedia , (which you could just do) but with blindfolds: I cannot look into "the bag" of x but only see my just-drawn item - this I found to be more like what you are asking for.

How do I go about solving this? Simple: I draw a value from x . Call it my control variable. Then for every draw I put the new value into a pile of small if less than (or equal) to control. Otherwise I put it into the large pile. When I have distributed all values, I do this algorithm again for each pile. I continue until my piles are all of size 1. The implementation of this below.

mysort <- function(x){
    if(length(x) <= 1){
        return(x)       ## If nothing to sort, return itself
    }

    control <- x[1]
    small <- c()
    big <- c()

    for(test in x[-1]){
        if(test <= control){
            small <- c(small,test)  ## Less than control in small
        }
        if(test > control){
            big <- c(big,test)      ## Bigger than control in big
        }
    }

    ## Sort the new piles with the same procedure recursively.
    small <- mysort(small)          
    big <- mysort(big)

    ## Return the improved order
    c(small,control,big)
}

mysort(c(2,1,1,2,2,2,3,3,-3,-Inf,Inf,0,pi))
# [1]      -Inf -3.000000  0.000000  1.000000  1.000000  2.000000  2.000000  2.000000
# [9]  2.000000  3.000000  3.000000  3.141593       Inf

We can compare speeds with the microbenchmark package, if we wrap your implementation (without the superfluous while -loop) in a function yoursort .

library(microbenchmark)
a <- rnorm(1e3)
microbenchmark(b <- mysort(a),times = 10)
# Unit: milliseconds
#           expr      min      lq     mean   median       uq      max neval
# b <- mysort(a) 37.76747 39.2302 41.96171 40.99288 43.07412 47.85377    10

microbenchmark(c <- yoursort(a),times = 10)
# Unit: milliseconds
#             expr      min       lq     mean   median       uq      max neval
# c <- yoursort(a) 786.4544 808.2312 861.8072 840.7868 879.4946 1059.913    10
microbenchmark(sort(a),times = 10)
# Unit: microseconds
#    expr     min      lq     mean   median      uq     max neval
# sort(a) 192.763 194.384 242.7633 201.1335 263.497 390.386    10

Neither are any match to the already implemented sort function.

And of course, do they actually do the correct sorting?

any(b != sort(a)) ## Are there any elements that do not match?
# [1] FALSE
any(c != sort(a))
# [1] FALSE

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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