Find the Kth smallest element

Posted on 2007-02-06 22:59  QT_pixy  阅读(980)  评论(0)    收藏  举报
Given a set of N comparable elements, we want to find the Kth smallest element (K≤N) in the collection (it would be the overall smallest if K=1). 
Use the partition method of the quick sort algorithm. Suppose it led to a partition of L and (N-1-L) elements. If L<K, I need to recur on only right side. Otherwise, I need to recur on only left side.

Note:   Since we are using median of three method to find pivot. We do not need to check from left to right, just from left+1 to right-1. But when we do partition later, we are going to do ++i and --j before checking. Then if we only have two elements, the Array index will go out of bound(- or + twice). So we need to deal with this case separately.
/**************************
 * The Kth smallest program
 *
 * Author: QT_pixy
 * Date: Feb. 5, 07
 *************************
*/


public class kthsmallest
{
    
public static <AnyType extends Comparable<? super AnyType>>
    AnyType FindKthSmallest(AnyType [] A, 
int k)
    
{
        
return Find(A, 0, A.length - 1, k);
    }

    
    
private static <AnyType extends Comparable<? super AnyType>>
    AnyType Find(AnyType [] A, 
int left, int right, int k)
    
{    
        
// checking base step
        if(left == right)
            
return A[left];
            
        
// Since we are using median of three method to find pivot.
        
// We do not need to check from left to right, just from left+1 to right-1.
        
// But when we do partition later, we are going to do ++i and --j before checking.
        
// Then if we only have two elements, the Array index will go out of bound(- or + twice).
        
// So we need to deal with this case separately.
        if(left + 1 == right)
        
{
            
if(A[left].compareTo(A[right]) > 0)
                swapReferences(A, left, right);
            
if(left + 1 == k)
                
return A[left];
            
if(right + 1 == k)
                
return A[right]; 
        }

        
        AnyType pivot 
= median3(A, left, right);
            
        
int i = left, j = right - 1;        // from left+1 to right - 1, since we use Median of three method,
                                        
// (since later we will ++i and --j)
                                        
// we do not need to worry about the first one and the last one.
    
        
for( ; ; )
        
{
            
while( A[++i].compareTo( pivot ) < 0 && i <= right - 1)
            
{
                
            }

            
while( A[--j].compareTo( pivot ) > 0 && j > left)
            
{
                
            }

            
if( i < j )
                swapReferences( A, i, j );
            
else
                
break;         
        }

        
           swapReferences( A, i, right 
- 1 );   // Restore pivot
           
           
if (i + 1 > k)
               
return Find(A, left, i - 1, k);
           
if (i + 1 < k)
               
return Find(A, i + 1, right, k);
           
else
               
return A[i];
    }


    
// The median-of-three method
    
//
    private static <AnyType extends Comparable<? super AnyType>>
    AnyType median3 (AnyType[] A, 
int left, int right)
    
{
        
int center = (left + right) / 2;
        
if (A[center].compareTo(A[left]) < 0 )
            swapReferences(A, left, center);
        
if (A[right].compareTo(A[left]) < 0)
            swapReferences(A, left, right);
        
if (A[right].compareTo(A[center]) < 0)
            swapReferences(A, right, center);

        swapReferences(A, center, right 
- 1);
        
return A[right - 1];

    }


    
private static <AnyType extends Comparable<? super AnyType>>
    
void swapReferences(AnyType [] A, int num1, int num2)
    
{
        AnyType temp 
= A[num1];
        A[num1] 
= A[num2];
        A[num2] 
= temp;
    }

}

This is the Main program which implement the routine above.
/**************************
 * The Kth smallest program
 *
 * Author: QT_pixy
 * Date: Feb. 5, 07
 *************************
*/


import java.util.Scanner;

public class Main2
{
    
public static  void main(String[] args)
    
{
        Integer [] A 
= {2344231312};
        
//Integer [] A = {10, 2, 5, 23, 45, 22, 23, 4, 14, 70, 62, 3, 20, 15, 24};

        
// You should use larger arrays for testing your program.

        Scanner input 
= new Scanner(System.in);

        
int k = input.nextInt();
        
        
while(k > 6 || k < 1)
        
{
            System.out.println(
"Try again!");
            k 
= input.nextInt();
        }

            
        Integer elem 
= kthsmallest.FindKthSmallest(A, k);
        System.out.println(elem);
    }

}

博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3