title: Efficient knn algorithm
body: <p>I'm trying to implement knn algorithm which operates on one dimensional vectors in R, but one which differs from the standard one just a bit, in that that it takes the smaller element in case of a tie (so the distance is just the absolute value of the difference between the attributes). More precisely, I'm trying to find k numbers which are the closest to a given number, and if there are ties I want the smaller number to be chosen.</p>
  
  <p>Sounds simple, but my algorithm takes couple of seconds to finish whilst the one that's in the class package (knn) outputs an answer immediately (though it takes all elements in case of a tie or random elements)... Mine's the following:</p>
  
  <ol>
  <li>I sample a training sample and order it increasingly.</li>
  <li>I take an element (a number) 
  2.5. and search for the first place in which it becomes less than some number in the training sample.</li>
  <li>I take 2k+1 numbers from the training sample -- k to the left of a number found in 2.5 and k to the right (if there are less than k such numbers, I take as much as I can).</li>
  <li>Finally I calculate the distances of chosen elements to the one I took in 2 and order them along with the corresponding elements increasingly (so that the elements and their distances are ordered increasingly)</li>
  <li>Then I take k first elements from the list created in 4. (so that no two have the same distance)</li>
  </ol>
  
  <p>But boy, it takes 6 or 7 seconds to finish... Do you have any ideas for an improvement? (It's not an R specific question, it just happened I do it in R).</p>
  
  <p>Edit. The code:</p>
  
  <pre><code>dec &lt;- function(u, x, k) {
  ## u is the training sample sorted increasingly
  ## x is an object for classification
  ## k is a knn parameter
  knn &lt;- list()
  i &lt;- 1
  div &lt;- 0
  for (j in u) {
      if (x &lt; j) {
          div &lt;- 0
          break
  }
      i &lt;- i+1
  }
  if (div == 0) {
      distances &lt;- array(0,dim=c(2,k))
      z &lt;- 1
      for (j in 1:k) {
          distances[1,z] &lt;- u[10000-j]
          distances[2,z] &lt;- abs(u[10000-j]-x)
      }
  } else {
      end1 &lt;- div+k
      end2 &lt;- div-k
      if (div&lt;k) {
          distances &lt;- array(0,dim=c(2,(div+k)))
          a &lt;- 1
          for (j in u[1:end1]) {
              distances[1,a] &lt;- j
              distances[2,a] &lt;- abs(j-x)
              a &lt;- a+1
          }
      } else if (10000-div&lt;k) {
          distances &lt;- array(0,dim=c(2,(1000-div+k)))
          a &lt;- 1
          for (j in u[end2:10000]) {
              distances[1,a] &lt;- j
              distances[2,a] &lt;- abs(j-x)
              a &lt;- a+1
          }
      } else {
          a &lt;- 1
          distances &lt;- array(0,dim=c(2,(2*k+1)))
          for (j in u[end1:end2]) {
              distances[1,a] &lt;- j
              distances[2,a] &lt;- abs(j-x)
              a &lt;- a+1
          }
      }
      distances &lt;- t(distances)
      distances &lt;- distances[ order( distances[,2], distances[,1]), ]
      distances &lt;- t(distances)
  }
  for (i in 1:k) {    
      if (i&gt;1 &amp;&amp; distances[1,i-1] != distances[1,i])
          knn[i] &lt;- distances[1,i]
  }
   ## and sth later...
  }
  </code></pre>